ECF / JaxRSProviders

Remote Services distribution provider based upon JaxRS. Includes imples based upon Jersey and CXF.
Apache License 2.0
13 stars 18 forks source link

Possible racecondition on Service creation and injection? #40

Closed nagelfargithub closed 2 years ago

nagelfargithub commented 2 years ago

This is an intermittent error that has been puzzeling me for some weeks now. Sometimes, when I start our RCP Client this fails with the following error logs `12.07.2021 15:46:37.513 [2bcb0ca164] [DEBUG] c.e.k.s.extension.KlvApiObjectMapper - Initialize new ObjectMapper. 12.07.2021 15:46:42.798 [ main] [INFO ] c.evolit.klv.ui.state.ApplicationState - ClientId set to 000C292A7378 org.eclipse.e4.core.di.InjectionException: Unable to process "LoginController.authService": no actual value was found for the argument "AuthenticationServiceInterface[@org.eclipse.e4.core.di.extensions.Service(filterExpression=, dynamic=true)]". at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:482) at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:473) at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129) at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405) at org.eclipse.e4.core.internal.di.InjectorImpl.resolveArgs(InjectorImpl.java:558) at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:463) at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129) at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405) at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:332) at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:202) at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:91) at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:60) at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:42) at org.eclipse.e4.ui.internal.workbench.swt.E4Application.lambda$0(E4Application.java:243) at java.util.Optional.ifPresent(Optional.java:159) at org.eclipse.e4.ui.internal.workbench.swt.E4Application.createE4Workbench(E4Application.java:242) at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:153) at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657) at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594) at org.eclipse.equinox.launcher.Main.run(Main.java:1447) at org.eclipse.equinox.launcher.Main.main(Main.java:1420) org.eclipse.e4.core.di.InjectionException: Unable to process "AbrechnungLoadService.abrechnungService": no actual value was found for the argument "AbrechnungServiceInterface[@org.eclipse.e4.core.di.extensions.Service(filterExpression=, dynamic=true)]". at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:482) at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:473) at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129) at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405) at org.eclipse.e4.core.internal.di.InjectorImpl.resolveArgs(InjectorImpl.java:558) at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:463) at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129) at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405) at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:332) at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:202) at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:91) at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:60) at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:42) at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.processActiveHandler(HandlerProcessingAddon.java:145) at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.handleContextEvent(HandlerProcessingAddon.java:127) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:58) at org.eclipse.e4.core.di.internal.extensions.EventObjectSupplier$DIEventHandler.handleEvent(EventObjectSupplier.java:92) at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:205) at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:203) at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1) at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:151) at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:132) at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:75) at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:44) at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:55) at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:63) at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:424) at org.eclipse.e4.ui.model.application.ui.basic.impl.WindowImpl.setContext(WindowImpl.java:521) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:635) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:766) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$0(PartRenderingEngine.java:737) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:731) at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:715) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1084) at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1047) at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155) at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:166) at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657) at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594) at org.eclipse.equinox.launcher.Main.run(Main.java:1447) at org.eclipse.equinox.launcher.Main.main(Main.java:1420) org.eclipse.e4.core.di.InjectionException: Unable to process "AbrechnungLoadService.abrechnungService": no actual value was found for the argument "AbrechnungServiceInterface[@org.eclipse.e4.core.di.extensions.Service(filterExpression=, dynamic=true)]". at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:482) at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:473) at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129) at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405) at org.eclipse.e4.core.internal.di.InjectorImpl.resolveArgs(InjectorImpl.java:558) at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:463) at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129) at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405) at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:332) at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:202) at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:91) at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:60) at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:42) at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.processActiveHandler(HandlerProcessingAddon.java:145) at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.handleContextEvent(HandlerProcessingAddon.java:127) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:58) at org.eclipse.e4.core.di.internal.extensions.EventObjectSupplier$DIEventHandler.handleEvent(EventObjectSupplier.java:92) at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:205) at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:203) at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1) at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:151) at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:132) at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:75) at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:44) at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:55) at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:63) at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:424) at org.eclipse.e4.ui.model.application.ui.basic.impl.WindowImpl.setContext(WindowImpl.java:521) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:635) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:766) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$0(PartRenderingEngine.java:737) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:731) at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:715) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1084) at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338) at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1047) at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155) at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:166) at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657) at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594) at org.eclipse.equinox.launcher.Main.run(Main.java:1447) at org.eclipse.equinox.launcher.Main.main(Main.java:1420) 15:46:46.404;IMPORT_REGISTRATION;importedSR={com.evolit.klv.service.AbrechnungServiceInterface, com.evolit.klv.service.AnwenderEinstellungServiceInterface, com.evolit.klv.service.AuthenticationServiceInterface, com.evolit.klv.service.BetreiberServiceInterface, com.evolit.klv.service.LookupServiceInterface, com.evolit.klv.service.RechnungServiceInterface, com.evolit.klv.service.TerminalServiceInterface, com.evolit.klv.service.NebengebuehrServiceInterface, com.evolit.klv.service.ITEVorgangServiceInterface, com.evolit.klv.service.ReportingServiceInterface, com.evolit.klv.service.LogEndToEndServiceInterface, com.evolit.klv.service.AbrechnungKorrekturServiceInterface, com.evolit.klv.service.KundenServiceInterface}={service.intents=osgi.async, service.id=170, service.bundleid=85, service.scope=bundle, osgi.basic.timeout=1800000, service.imported.configs=[ecf.jaxrs.jersey.client], endpoint.id=[redacted], service.imported=org.eclipse.ecf.provider.jaxrs.client.JaxRSClientContainer$JaxRSClientRemoteService@fbce72};cID=URIID [uri=[redacted];rsId=0 --Endpoint Description---

com.evolit.klv.service.AbrechnungServiceInterface com.evolit.klv.service.AnwenderEinstellungServiceInterface com.evolit.klv.service.AuthenticationServiceInterface com.evolit.klv.service.BetreiberServiceInterface com.evolit.klv.service.LookupServiceInterface com.evolit.klv.service.RechnungServiceInterface com.evolit.klv.service.TerminalServiceInterface com.evolit.klv.service.NebengebuehrServiceInterface com.evolit.klv.service.ITEVorgangServiceInterface com.evolit.klv.service.ReportingServiceInterface com.evolit.klv.service.LogEndToEndServiceInterface com.evolit.klv.service.AbrechnungKorrekturServiceInterface com.evolit.klv.service.KundenServiceInterface ecf.jaxrs.jersey.server passByValue exactlyOnce ordered jaxrs ecf.jaxrs.jersey.client

---End Endpoint Description`

If I close the client and restart everything works fine. This happens perhaps one in ten times, perhaps even less and it is impossible for us to force it in our DEV environment, it NEVER happens when we start directly from Eclipse (tried literally dozens of time) only when we start the built client.

Unfortunately the above is the only "good" log I have of such an issue but it makes me think that there might be a race condition where the dependency injection already tries to inject while our services are not ready yet, what is your opinion here, is that possible? Perhaps related to our startlevels? image

Like for example the bundle handling the DI and the jersey bundles run at the same time and in 99% of the time jersey/ecf finishes before DI kicks in but just sometimes it doesn't? If so, what should we change on start-levels or is there another way we could prevent this?

nagelfargithub commented 2 years ago

Some additional information: I'm now almost 100% sure it is happening as described, declarative services are still being setup (so the jaxrsprovider is not ready yet) but the @PostContextCreate event is already fired. I have a LifecycleManager class listening to this event but when the services are not ready yet the annotated method is never called as OSGI is not able to Inject my services.

Do you have any input on why this could be happening or how to prevent it?

scottslewis commented 2 years ago

Hi. Looking at the stack trace, I suspect that you are using the e4 injection mechanism, rather than DS/OSGi injection since these stack frames

org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:482) at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:473) at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129) at

are the e4 injection mechanism, not the OSGi/DS/scr.

I'm also a little confused about what you are trying to do. Are you trying to have the jersey impl use some sort of extension/ObjectMapper? If so, the better way to do this could be to use the extension mechanism built into the ECF jaxrs provider impl, which registers extensions during container initialization, where the extensions are registered as services. For an example, see this project: https://github.com/ECF/JaxRSProviders/tree/master/examples/org.eclipse.ecf.example.jersey.server.basicauth

What this does is setup a ContainerRequestFilter jaxrs extension in jersey (see the single class in this project) with this component declaration:

@Component(immediate = true, property = { "jaxrs-service-exported-config-target=ecf.jaxrs.jersey.server", "jaxrs-component-intents=ecf.jaxrs.basicauth" }) public class BasicAuthContainerRequestFilter implements ContainerRequestFilter {

note that this property: jaxrs-service-exported-config-target=ecf.jaxrs.jersey.server sets up the association between the container config type (ecf.jaxrs.jersey.server) and the component (BasicAuthContainerRequestFilter). What happens is that ECF's JaxRS impl read all of the associated components from service registry that match the container/config type being created (in this case 'ecf.jaxrs.jersey.server' and registers the extension at container setup/creation time). And then when a request comes into the ecf.jaxrs.jersey.server instance, it calls the BasicAuthContainerRequestFilter to process before actually handling the request.

It's going to be very difficult to manage the timing of the jersey extension config via e4 injection, as things are done asynchronously via event processing, and that seems like the likely suspect in your race.

Let me know if I can help further. My intention is to create some more examples of Jaxrs extension/configuration, perhaps I could use your use case to do so.

nagelfargithub commented 2 years ago

Yes, we are developing an e4 based eclipse RCP client.

Also yes, we are registering a couple of extensions/filters. The ObjectMapper

<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="com.evolit.klv.service.extension.KlvApiObjectMapper">
   <implementation class="com.evolit.klv.service.extension.KlvApiObjectMapper"/>
   <service>
      <provide interface="javax.ws.rs.ext.ContextResolver"/>
   </service>
</scr:component>

The code


import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

@Component(service = ContextResolver.class)
public class KlvApiObjectMapper implements ContextResolver<ObjectMapper> {
    private static final Logger log = LoggerFactory.getLogger(KlvApiObjectMapper.class);

    private ObjectMapper objectMapper;

    public KlvApiObjectMapper() {
        log.debug("Initialize new ObjectMapper.");
        objectMapper = new ObjectMapper()
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
                .registerModule(new JavaTimeModule());          
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        log.trace("Get existing object mapper");
        return objectMapper;
    }

}

Two filters

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="com.evolit.klv.service.extension.RequestLoggingFilter">
   <service>
      <provide interface="javax.ws.rs.client.ClientRequestFilter"/>
   </service>
   <implementation class="com.evolit.klv.service.extension.RequestLoggingFilter"/>
</scr:component>

and

<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="com.evolit.klv.service.extension.ResponseLoggingFilter">
   <service>
      <provide interface="javax.ws.rs.client.ClientResponseFilter"/>
   </service>
   <implementation class="com.evolit.klv.service.extension.ResponseLoggingFilter"/>
</scr:component>

The code

import java.io.IOException;
import java.util.UUID;

import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;

import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.evolit.klv.service.logendtoend.LogEndToEndStore;
import com.evolit.klv.shared.constants.Endpoints;

@Component(service = ClientRequestFilter.class)
public class RequestLoggingFilter implements ClientRequestFilter {
    private static final Logger log = LoggerFactory.getLogger(RequestLoggingFilter.class);

    @Override
    public void filter(ClientRequestContext requestCtx) throws IOException {
        log.debug("Starting REST-API call - method: {}, uri: {}, entityClass: {}", requestCtx.getMethod(), requestCtx.getUri(), requestCtx.getEntityClass());
        //ignore calls to LogEndToEnd as that would lead to logging calls to LogEndToEnd
        if(!requestCtx.getUri().toString().contains(Endpoints.LOG_END_TO_END)) {
            String endToEndLoggingId = UUID.randomUUID().toString();        
            requestCtx.setProperty(KLVClientFilter.END_TO_END_LOGGING_ID, endToEndLoggingId);
            LogEndToEndStore.getInstance().start(endToEndLoggingId, requestCtx.getMethod() + " " + requestCtx.getUri().getPath());
        }

    }
}

and


import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientResponseContext;
import javax.ws.rs.client.ClientResponseFilter;

import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.evolit.klv.service.logendtoend.LogEndToEndStore;

@Component(service = ClientResponseFilter.class)
public class ResponseLoggingFilter extends KLVClientFilter implements ClientResponseFilter {
    private static final Logger log = LoggerFactory.getLogger(ResponseLoggingFilter.class);

    @Override
    public void filter(ClientRequestContext requestCtx, ClientResponseContext responseCtx) throws IOException {
        String endToEndLoggingId = (String)requestCtx.getProperty(KLVClientFilter.END_TO_END_LOGGING_ID);
        if(endToEndLoggingId != null) {
            LogEndToEndStore.getInstance().done(endToEndLoggingId);
        }
        if (!isOkResponse(responseCtx)) {
            log.warn("REST-API call failed: {}", responseCtx);
        } else {
            log.debug("REST-API call successful: {}", responseCtx);
        }
    }
}

And some SessionFilter

<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="com.evolit.klv.service.extension.StoreSessionIdFilter">
   <service>
      <provide interface="javax.ws.rs.client.ClientResponseFilter"/>
   </service>
   <implementation class="com.evolit.klv.service.extension.StoreSessionIdFilter"/>
</scr:component>

the code


import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientResponseContext;
import javax.ws.rs.client.ClientResponseFilter;

import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.evolit.klv.shared.constants.Endpoints;

@Component(service = ClientResponseFilter.class)
public class StoreSessionIdFilter extends KLVClientFilter implements ClientResponseFilter {
    private static final Logger log = LoggerFactory.getLogger(StoreSessionIdFilter.class);
    private static final String SESSION_ID_COOKIE_NAME = "JSESSIONID";

    private boolean isLogout(ClientRequestContext requestCtx) {
        return Endpoints.LOGOUT.equalsIgnoreCase(requestCtx.getUri().getPath());
    }

    @Override
    public void filter(ClientRequestContext requestCtx, ClientResponseContext responseCtx) throws IOException {
        if (isLogout(requestCtx) && isOkResponse(responseCtx)) {
            log.debug("Logout request was successful. Close the session");
            SessionIdStore.getInstance().closeSession();
        } else {
            responseCtx.getCookies().values().stream()
                .filter(c -> SESSION_ID_COOKIE_NAME.equals(c.getName()))
                .findAny()
                .ifPresent(SessionIdStore.getInstance()::setSessionCookie);
        }
    }
}

So, what you are saying is that because we are using jersey extension config this clashes with 4e injections as things are done asynchronously and there is no way around it? Feel free to use any of the provided code to setup your examples.

scottslewis commented 2 years ago

Yes, we are developing an e4 based eclipse RCP client.

``` So, what you are saying is that because we are using jersey extension config this clashes with 4e injections as things are done asynchronously and there is no way around it?

I do think that these issues are causing races...because of the asynchronous processing of DS relative to the e4 injection. To be honest, I don't know enough about the e4 injection mechanism to know whether you can (e.g.) 'wait for a DS service t appear'...before doing the e4 injection. If such a mechanism does exist in e4 injection then you could probably use it to sequence the startup/initialization/extension registration/jersey provider creation/export, etc.

You could probably also use start levels, but that would be very brittle and not a good idea at all IMHO.

What I would suggest as a way to deal with it is to use the mechanism I've got built into the jaxrs/jersey distribution provider (using DS) to register jax rs extensions (e.g. ClientResponseFilter) to assure (via ds dependency management) that jax rs extensions get processed and registered with the jaxrs impl (i.e. jersey in this case) before the server (or client) is setup and started.

Feel free to use any of the provided code to setup your examples.

Just as an example I think you (or I) could take your impl and modify it like this:

import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientResponseContext;
import javax.ws.rs.client.ClientResponseFilter;

import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.evolit.klv.shared.constants.Endpoints;

@Component(immediate = true, service = ClientResponseFilter.class, , property = { "jaxrs-service-exported-config-target=ecf.jaxrs.jersey.client" ))
public class StoreSessionIdFilter extends KLVClientFilter implements ClientResponseFilter {
    private static final Logger log = LoggerFactory.getLogger(StoreSessionIdFilter.class);
    private static final String SESSION_ID_COOKIE_NAME = "JSESSIONID";

    private boolean isLogout(ClientRequestContext requestCtx) {
        return Endpoints.LOGOUT.equalsIgnoreCase(requestCtx.getUri().getPath());
    }

    @Override
    public void filter(ClientRequestContext requestCtx, ClientResponseContext responseCtx) throws IOException {
        if (isLogout(requestCtx) && isOkResponse(responseCtx)) {
            log.debug("Logout request was successful. Close the session");
            SessionIdStore.getInstance().closeSession();
        } else {
            responseCtx.getCookies().values().stream()
                .filter(c -> SESSION_ID_COOKIE_NAME.equals(c.getName()))
                .findAny()
                .ifPresent(SessionIdStore.getInstance()::setSessionCookie);
        }
    }
}

This annotation in the above is slightly different:

@Component(immediate = true, service = ClientResponseFilter.class, , property = { "jaxrs-service-exported-config-target=ecf.jaxrs.jersey.server" ))

The immediate = true will assure that the component is registered in service registry when the bundle that contains it is started.

the property = { "jaxrs-service-exported-config-target=ecf.jaxrs.jersey.server" ))

tells the ECF jaxrs distribution provider that *when creating a ecf.jaxrs.jersey.server distribution provider, as part of it's initialization (before usage/service export or import) register thie ClientResponseFilter on the Client instance under creation...so that later, when the client makes a request and then receives a response, that Jersey/jaxrs impl calls your ClientResponseFilter before the proxy returns the response.

I added this processing (i.e. with the service property) because I knew that people would want to extend jersey/jaxrs impl, and since the Remote Services spec doesn't provide any way to hook into the jaxrs Client or Server extension registration mechanism (as part of the spec), that the ECF impl would have to provide it in the dynamic OSGi environment which is much more dynamic/less static than the 'typical' jaxrs/Jersey environment. Fortunately, using DS whiteboard registration of services...and then processing/registering them at the right point in the ServerContainer or ClientContainer initialization allows the ECF remote services provider do this.

I'm willing to help with this and so I think I'll create one component from above as an example. Which one would you prefer I use to begin with?

Thanks.

Scott

nagelfargithub commented 2 years ago

So, looking at your code only the @Component Annotation is changed, correct? I'll give this a try using the example you provided. Would it look the same e.g. for the KlvApiObjectMapper?

@Component(immediate = true, service = ContextResolver.class, property = { "jaxrs-service-exported-config-target=ecf.jaxrs.jersey.client"} )
public class KlvApiObjectMapper implements ContextResolver<ObjectMapper> {

etc?

Any changes to the XML necessary?

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="com.evolit.klv.service.extension.KlvApiObjectMapper">
   <implementation class="com.evolit.klv.service.extension.KlvApiObjectMapper"/>
   <service>
      <provide interface="javax.ws.rs.ext.ContextResolver"/>
   </service>
</scr:component>

Because your example looks different but it gives the same additional properties as provided with the annotation?

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="org.eclipse.ecf.example.jersey.server.basicauth.BasicAuthContainerRequestFilter">
   <property name="jaxrs-service-exported-config-target" value="ecf.jaxrs.jersey.server"/>
   <property name="jaxrs-component-intents" value="ecf.jaxrs.basicauth"/>
   <service>
      <provide interface="javax.ws.rs.container.ContainerRequestFilter"/>
   </service>
   <implementation class="org.eclipse.ecf.example.jersey.server.basicauth.BasicAuthContainerRequestFilter"/>
</scr:component>
scottslewis commented 2 years ago

Yes...there are changes to the XML. I'm not sure how you are creating the XML, but frequently it gets created at compile time by processing the @Component annotation. So...yes your xml component spec should look something like:

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="com.evolit.klv.service.extension.KlvApiObjectMapper">
   <implementation class="com.evolit.klv.service.extension.KlvApiObjectMapper"/>
   <service>
      <provide interface="javax.ws.rs.ext.ContextResolver"/>
   </service>
   <property name="jaxrs-service-exported-config-target" value="ecf.jaxrs.jersey.server"/>
</scr:component>
nagelfargithub commented 2 years ago

Just to clarify, I'm only talking about a client implementation here so one thought: config-target should be jersey.client not jersey.server for the client component.

scottslewis commented 2 years ago

That's correct...for client side: ecf.jaxrs.jersey.client and for server side: ecf.jaxrs.jersey.server

nagelfargithub commented 2 years ago

I implemented all the changes but unfortunately this is still bugging us, I finally managed to get a full log/stacktrace

18:04:33.407 [Start Level: Equinox Container: d0553025-e525-419e-bde1-51c3d73af340] DEBUG c.e.k.s.extension.KlvApiObjectMapper - Initialize new ObjectMapper.
18:04:33.745 [Start Level: Equinox Container: d0553025-e525-419e-bde1-51c3d73af340] INFO  c.e.k.service.KLVUpdateManagerLogger - Initialize new KLVUpdateManagerLogger
14.12.2021 18:04:39.822 [      main] [INFO ]  c.evolit.klv.ui.state.ApplicationState   - ApplicationState init
14.12.2021 18:04:39.930 [      main] [INFO ]  c.evolit.klv.ui.state.ApplicationState   - ClientId set to 000C29F2FE17
org.eclipse.e4.core.di.InjectionException: Unable to process "LoginController.authService": no actual value was found for the argument "AuthenticationServiceInterface[@org.eclipse.e4.core.di.extensions.Service(filterExpression="", dynamic=true)]".
        at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:482)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:473)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveArgs(InjectorImpl.java:558)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:463)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405)
        at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:332)
        at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:202)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:91)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:60)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:42)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application.lambda$0(E4Application.java:243)
        at java.base/java.util.Optional.ifPresent(Optional.java:183)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application.createE4Workbench(E4Application.java:242)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:153)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1447)
!SESSION 2021-12-14 18:04:28.121 -----------------------------------------------
eclipse.buildId=unknown
java.version=11.0.2
java.vendor=Oracle Corporation
BootLoader constants: OS=win32, ARCH=x86_64, WS=win32, NL=de_DE
Framework arguments:  -clearPersistedState -debug
Command-line arguments:  -os win32 -ws win32 -arch x86_64 -clearPersistedState -debug -consoleLog

!ENTRY org.eclipse.e4.ui.workbench 4 0 2021-12-14 18:04:39.955
!MESSAGE Unable to create class 'com.evolit.klv.ui.LifeCycleManager' from bundle '194'
!STACK 0
org.eclipse.e4.core.di.InjectionException: Unable to process "LifeCycleManager.loginController": no actual value was found for the argument "LoginController".
        at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:482)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:473)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405)
        at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:332)
        at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:202)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:91)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:60)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:42)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application.lambda$0(E4Application.java:243)
        at java.base/java.util.Optional.ifPresent(Optional.java:183)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application.createE4Workbench(E4Application.java:242)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:153)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1447)
org.eclipse.e4.core.di.InjectionException: Unable to process "AbrechnungLoadService.abrechnungService": no actual value was found for the argument "AbrechnungServiceInterface[@org.eclipse.e4.core.di.extensions.Service(filterExpression="", dynamic=true)]".
        at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:482)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:473)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveArgs(InjectorImpl.java:558)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:463)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405)
        at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:332)
        at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:202)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:91)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:60)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:42)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.processActiveHandler(HandlerProcessingAddon.java:145)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.handleContextEvent(HandlerProcessingAddon.java:127)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:58)
        at org.eclipse.e4.core.di.internal.extensions.EventObjectSupplier$DIEventHandler.handleEvent(EventObjectSupplier.java:92)
        at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:205)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:203)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1)
        at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234)
        at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:151)
        at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:132)
        at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:75)
        at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:44)
        at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:55)
        at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:63)
        at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:424)
        at org.eclipse.e4.ui.model.application.ui.basic.impl.WindowImpl.setContext(WindowImpl.java:521)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:635)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:766)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$0(PartRenderingEngine.java:737)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:731)
        at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:715)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1084)
        at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1047)
        at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:166)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1447)

!ENTRY org.eclipse.e4.ui.workbench 4 0 2021-12-14 18:04:40.998
!MESSAGE Unable to create class 'com.evolit.klv.ui.handler.AbrechnungHandler' from bundle '194'
!STACK 0
org.eclipse.e4.core.di.InjectionException: Unable to process "AbrechnungHandler.abrechnungService": no actual value was found for the argument "AbrechnungLoadService".
        at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:482)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:473)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405)
        at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:332)
        at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:202)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:91)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:60)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:42)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.processActiveHandler(HandlerProcessingAddon.java:145)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.handleContextEvent(HandlerProcessingAddon.java:127)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:58)
        at org.eclipse.e4.core.di.internal.extensions.EventObjectSupplier$DIEventHandler.handleEvent(EventObjectSupplier.java:92)
        at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:205)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:203)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1)
        at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234)
        at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:151)
        at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:132)
        at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:75)
        at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:44)
        at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:55)
        at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:63)
        at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:424)
        at org.eclipse.e4.ui.model.application.ui.basic.impl.WindowImpl.setContext(WindowImpl.java:521)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:635)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:766)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$0(PartRenderingEngine.java:737)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:731)
        at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:715)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1084)
        at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1047)
        at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:166)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1447)

!ENTRY org.eclipse.e4.ui.workbench 4 0 2021-12-14 18:04:41.019
!MESSAGE Unable to create class 'com.evolit.klv.ui.handler.AnwenderEinstellungSaveHandler' from bundle '194'
!STACK 0
org.eclipse.e4.core.di.InjectionException: Unable to process "AnwenderEinstellungSaveHandler.anwenderEinstellungService": no actual value was found for the argument "AnwenderEinstellungServiceInterface[@org.eclipse.e4.core.di.extensions.Service(filterExpression="", dynamic=true)]".
        at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:482)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:473)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405)
        at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:332)
        at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:202)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:91)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:60)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:42)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.processActiveHandler(HandlerProcessingAddon.java:145)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.handleContextEvent(HandlerProcessingAddon.java:127)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:58)
        at org.eclipse.e4.core.di.internal.extensions.EventObjectSupplier$DIEventHandler.handleEvent(EventObjectSupplier.java:92)
        at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:205)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:203)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1)
        at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234)
        at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:151)
        at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:132)
        at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:75)
        at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:44)
        at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:55)
        at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:63)
        at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:424)
        at org.eclipse.e4.ui.model.application.ui.basic.impl.WindowImpl.setContext(WindowImpl.java:521)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:635)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:766)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$0(PartRenderingEngine.java:737)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:731)
        at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:715)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1084)
        at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1047)
        at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:166)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1447)

!ENTRY org.eclipse.e4.ui.workbench 4 0 2021-12-14 18:04:41.025
!MESSAGE Unable to create class 'com.evolit.klv.ui.handler.AnwenderEinstellungAbbrechenHandler' from bundle '194'
!STACK 0
org.eclipse.e4.core.di.InjectionException: Unable to process "AnwenderEinstellungAbbrechenHandler.anwenderEinstellungService": no actual value was found for the argument "AnwenderEinstellungServiceInterface[@org.eclipse.e4.core.di.extensions.Service(filterExpression="", dynamic=true)]".
        at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:482)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:473)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405)
        at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:332)
        at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:202)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:91)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:60)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:42)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.processActiveHandler(HandlerProcessingAddon.java:145)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.handleContextEvent(HandlerProcessingAddon.java:127)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:58)
        at org.eclipse.e4.core.di.internal.extensions.EventObjectSupplier$DIEventHandler.handleEvent(EventObjectSupplier.java:92)
        at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:205)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:203)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1)
        at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234)
        at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:151)
        at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:132)
        at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:75)
        at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:44)
        at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:55)
        at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:63)
        at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:424)
        at org.eclipse.e4.ui.model.application.ui.basic.impl.WindowImpl.setContext(WindowImpl.java:521)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:635)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:766)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$0(PartRenderingEngine.java:737)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:731)
        at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:715)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1084)
        at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1047)
        at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:166)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1447)

!ENTRY org.eclipse.e4.ui.workbench 4 0 2021-12-14 18:04:41.037
!MESSAGE Unable to create class 'com.evolit.klv.ui.handler.UpdateNBGHandler' from bundle '194'
!STACK 0
org.eclipse.e4.core.di.InjectionException: Unable to process "UpdateNBGHandler.nebengebuehrService": no actual value was found for the argument "NebengebuehrServiceInterface[@org.eclipse.e4.core.di.extensions.Service(filterExpression="", dynamic=true)]".
        at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:482)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:473)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405)
        at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:332)
        at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:202)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:91)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:60)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:42)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.processActiveHandler(HandlerProcessingAddon.java:145)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.handleContextEvent(HandlerProcessingAddon.java:127)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:58)
        at org.eclipse.e4.core.di.internal.extensions.EventObjectSupplier$DIEventHandler.handleEvent(EventObjectSupplier.java:92)
        at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:205)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:203)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1)
        at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234)
        at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:151)
        at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:132)
        at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:75)
        at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:44)
        at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:55)
        at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:63)
        at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:424)
        at org.eclipse.e4.ui.model.application.ui.basic.impl.WindowImpl.setContext(WindowImpl.java:521)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:635)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:766)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$0(PartRenderingEngine.java:737)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:731)
        at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:715)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1084)
        at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1047)
        at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:166)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1447)

!ENTRY org.eclipse.e4.ui.workbench 4 0 2021-12-14 18:04:41.054
!MESSAGE Unable to create class 'com.evolit.klv.ui.handler.NBGSelectionChangedHandler' from bundle '194'
!STACK 0
org.eclipse.e4.core.di.InjectionException: Unable to process "NBGSelectionChangedHandler.iteVorgangService": no actual value was found for the argument "ITEVorgangServiceInterface[@org.eclipse.e4.core.di.extensions.Service(filterExpression="", dynamic=true)]".
        at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:482)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:473)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405)
        at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:332)
        at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:202)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:91)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:60)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:42)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.processActiveHandler(HandlerProcessingAddon.java:145)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.handleContextEvent(HandlerProcessingAddon.java:127)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:58)
        at org.eclipse.e4.core.di.internal.extensions.EventObjectSupplier$DIEventHandler.handleEvent(EventObjectSupplier.java:92)
        at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:205)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:203)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1)
        at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234)
        at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:151)
        at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:132)
        at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:75)
        at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:44)
        at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:55)
        at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:63)
        at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:424)
        at org.eclipse.e4.ui.model.application.ui.basic.impl.WindowImpl.setContext(WindowImpl.java:521)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:635)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:766)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$0(PartRenderingEngine.java:737)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:731)
        at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:715)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1084)
        at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1047)
        at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:166)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1447)

!ENTRY org.eclipse.e4.ui.workbench 4 0 2021-12-14 18:04:41.069
!MESSAGE Unable to create class 'com.evolit.klv.ui.handler.NewEmailSuggestionsHandler' from bundle '194'
!STACK 0
org.eclipse.e4.core.di.InjectionException: Unable to process "NewEmailSuggestionsHandler.anwenderEinstellungService": no actual value was found for the argument "AnwenderEinstellungServiceInterface[@org.eclipse.e4.core.di.extensions.Service(filterExpression="", dynamic=true)]".
        at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:482)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:473)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405)
        at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:332)
        at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:202)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:91)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:60)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:42)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.processActiveHandler(HandlerProcessingAddon.java:145)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.handleContextEvent(HandlerProcessingAddon.java:127)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:58)
        at org.eclipse.e4.core.di.internal.extensions.EventObjectSupplier$DIEventHandler.handleEvent(EventObjectSupplier.java:92)
        at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:205)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:203)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1)
        at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234)
        at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:151)
        at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:132)
        at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:75)
        at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:44)
        at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:55)
        at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:63)
        at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:424)
        at org.eclipse.e4.ui.model.application.ui.basic.impl.WindowImpl.setContext(WindowImpl.java:521)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:635)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:766)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$0(PartRenderingEngine.java:737)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:731)
        at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:715)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1084)
        at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1047)
        at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:166)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1447)

!ENTRY org.eclipse.e4.ui.workbench 4 0 2021-12-14 18:04:41.089
!MESSAGE Unable to create class 'com.evolit.klv.ui.handler.KorrekturHandler' from bundle '194'
!STACK 0
org.eclipse.e4.core.di.InjectionException: Unable to process "KorrekturHandler.abrechnungKorrekturServiceInterface": no actual value was found for the argument "AbrechnungKorrekturServiceInterface[@org.eclipse.e4.core.di.extensions.Service(filterExpression="", dynamic=true)]".
        at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:482)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:473)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405)
        at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:332)
        at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:202)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:91)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:60)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:42)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.processActiveHandler(HandlerProcessingAddon.java:145)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.handleContextEvent(HandlerProcessingAddon.java:127)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:58)
        at org.eclipse.e4.core.di.internal.extensions.EventObjectSupplier$DIEventHandler.handleEvent(EventObjectSupplier.java:92)
        at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:205)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:203)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1)
        at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234)
        at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:151)
        at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:132)
        at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:75)
        at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:44)
        at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:55)
        at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:63)
        at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:424)
        at org.eclipse.e4.ui.model.application.ui.basic.impl.WindowImpl.setContext(WindowImpl.java:521)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:635)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:766)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$0(PartRenderingEngine.java:737)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:731)
        at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:715)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1084)
        at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1047)
        at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:166)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1447)
org.eclipse.e4.core.di.InjectionException: Unable to process "AbrechnungLoadService.abrechnungService": no actual value was found for the argument "AbrechnungServiceInterface[@org.eclipse.e4.core.di.extensions.Service(filterExpression="", dynamic=true)]".
        at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:482)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:473)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveArgs(InjectorImpl.java:558)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:463)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405)
        at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:332)
        at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:202)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:91)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:60)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:42)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.processActiveHandler(HandlerProcessingAddon.java:145)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.handleContextEvent(HandlerProcessingAddon.java:127)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:58)
        at org.eclipse.e4.core.di.internal.extensions.EventObjectSupplier$DIEventHandler.handleEvent(EventObjectSupplier.java:92)
        at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:205)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:203)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1)
        at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234)
        at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:151)
        at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:132)
        at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:75)
        at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:44)
        at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:55)
        at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:63)
        at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:424)
        at org.eclipse.e4.ui.model.application.ui.basic.impl.WindowImpl.setContext(WindowImpl.java:521)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:635)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:766)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$0(PartRenderingEngine.java:737)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:731)
        at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:715)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1084)
        at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1047)
        at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:166)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1447)

!ENTRY org.eclipse.e4.ui.workbench 4 0 2021-12-14 18:04:41.158
!MESSAGE Unable to create class 'com.evolit.klv.ui.handler.abrechnung.LoadRechnungenHandler' from bundle '194'
!STACK 0
org.eclipse.e4.core.di.InjectionException: Unable to process "LoadRechnungenHandler.abrechnungService": no actual value was found for the argument "AbrechnungLoadService".
        at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:482)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:473)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405)
        at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:332)
        at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:202)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:91)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:60)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:42)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.processActiveHandler(HandlerProcessingAddon.java:145)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.handleContextEvent(HandlerProcessingAddon.java:127)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:58)
        at org.eclipse.e4.core.di.internal.extensions.EventObjectSupplier$DIEventHandler.handleEvent(EventObjectSupplier.java:92)
        at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:205)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:203)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1)
        at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234)
        at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:151)
        at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:132)
        at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:75)
        at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:44)
        at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:55)
        at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:63)
        at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:424)
        at org.eclipse.e4.ui.model.application.ui.basic.impl.WindowImpl.setContext(WindowImpl.java:521)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:635)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:766)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$0(PartRenderingEngine.java:737)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:731)
        at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:715)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1084)
        at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1047)
        at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:166)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1447)
org.eclipse.e4.core.di.InjectionException: Unable to process "KonzernClientService.konzernService": no actual value was found for the argument "KonzernServiceInterface[@org.eclipse.e4.core.di.extensions.Service(filterExpression="", dynamic=true)]".
        at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:482)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:473)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveArgs(InjectorImpl.java:558)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:463)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405)
        at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:332)
        at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:202)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:91)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:60)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:42)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.processActiveHandler(HandlerProcessingAddon.java:145)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.handleContextEvent(HandlerProcessingAddon.java:127)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:58)
        at org.eclipse.e4.core.di.internal.extensions.EventObjectSupplier$DIEventHandler.handleEvent(EventObjectSupplier.java:92)
        at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:205)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:203)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1)
        at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234)
        at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:151)
        at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:132)
        at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:75)
        at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:44)
        at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:55)
        at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:63)
        at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:424)
        at org.eclipse.e4.ui.model.application.ui.basic.impl.WindowImpl.setContext(WindowImpl.java:521)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:635)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:766)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$0(PartRenderingEngine.java:737)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:731)
        at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:715)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1084)
        at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1047)
        at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:166)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1447)

!ENTRY org.eclipse.e4.ui.workbench 4 0 2021-12-14 18:04:41.246
!MESSAGE Unable to create class 'com.evolit.klv.ui.handler.KonzernverwaltungHandler' from bundle '194'
!STACK 0
org.eclipse.e4.core.di.InjectionException: Unable to process "KonzernverwaltungHandler.konzernService": no actual value was found for the argument "KonzernClientService".
        at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:482)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:473)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405)
        at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:332)
        at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:202)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:91)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:60)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:42)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.processActiveHandler(HandlerProcessingAddon.java:145)
        at org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon.handleContextEvent(HandlerProcessingAddon.java:127)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:58)
        at org.eclipse.e4.core.di.internal.extensions.EventObjectSupplier$DIEventHandler.handleEvent(EventObjectSupplier.java:92)
        at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:205)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:203)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1)
        at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234)
        at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:151)
        at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:132)
        at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:75)
        at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:44)
        at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:55)
        at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:63)
        at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:424)
        at org.eclipse.e4.ui.model.application.ui.basic.impl.WindowImpl.setContext(WindowImpl.java:521)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:635)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:766)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$0(PartRenderingEngine.java:737)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:731)
        at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:715)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1084)
        at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1047)
        at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:166)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1447)

!ENTRY org.eclipse.e4.ui.workbench 4 0 2021-12-14 18:04:41.927
!MESSAGE Unable to create class 'com.evolit.klv.ui.part.DashboardPart' from bundle '194'
!STACK 0
org.eclipse.e4.core.di.InjectionException: Unable to process "DashboardPart.anwenderEinstellungService": no actual value was found for the argument "AnwenderEinstellungServiceInterface[@org.eclipse.e4.core.di.extensions.Service(filterExpression="", dynamic=true)]".
        at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:482)
        at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:473)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:129)
        at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:405)
        at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:332)
        at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:202)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:91)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:60)
        at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:42)
        at org.eclipse.e4.ui.workbench.renderers.swt.ContributedPartRenderer.createWidget(ContributedPartRenderer.java:132)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createWidget(PartRenderingEngine.java:1000)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:660)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:766)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$0(PartRenderingEngine.java:737)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:731)
        at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:715)
        at org.eclipse.e4.ui.workbench.renderers.swt.SWTPartRenderer.processContents(SWTPartRenderer.java:71)
        at org.eclipse.e4.ui.workbench.renderers.swt.PerspectiveRenderer.processContents(PerspectiveRenderer.java:51)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:674)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:766)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$0(PartRenderingEngine.java:737)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:731)
        at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:715)
        at org.eclipse.e4.ui.workbench.renderers.swt.PerspectiveStackRenderer.showTab(PerspectiveStackRenderer.java:82)
        at org.eclipse.e4.ui.workbench.renderers.swt.LazyStackRenderer.lambda$0(LazyStackRenderer.java:75)
        at org.eclipse.e4.ui.services.internal.events.UIEventHandler.lambda$0(UIEventHandler.java:38)
        at org.eclipse.swt.widgets.Synchronizer.syncExec(Synchronizer.java:236)
        at org.eclipse.swt.widgets.Display.syncExec(Display.java:4735)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application$1.syncExec(E4Application.java:219)
        at org.eclipse.e4.ui.services.internal.events.UIEventHandler.handleEvent(UIEventHandler.java:38)
        at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:205)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:203)
        at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1)
        at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234)
        at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:151)
        at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:132)
        at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:75)
        at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:44)
        at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:55)
        at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:63)
        at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:424)
        at org.eclipse.e4.ui.model.application.ui.advanced.impl.PerspectiveStackImpl.setSelectedElement(PerspectiveStackImpl.java:152)
        at org.eclipse.e4.ui.model.application.ui.advanced.impl.PerspectiveStackImpl.setSelectedElement(PerspectiveStackImpl.java:1)
        at org.eclipse.e4.ui.workbench.renderers.swt.LazyStackRenderer.postProcess(LazyStackRenderer.java:110)
        at org.eclipse.e4.ui.workbench.renderers.swt.PerspectiveStackRenderer.postProcess(PerspectiveStackRenderer.java:64)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:678)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:766)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$0(PartRenderingEngine.java:737)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:731)
        at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:715)
        at org.eclipse.e4.ui.workbench.renderers.swt.SWTPartRenderer.processContents(SWTPartRenderer.java:71)
        at org.eclipse.e4.ui.workbench.renderers.swt.WBWRenderer.processContents(WBWRenderer.java:666)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:674)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:766)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$0(PartRenderingEngine.java:737)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$2.run(PartRenderingEngine.java:731)
        at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:715)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1084)
        at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
        at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1047)
        at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
        at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:166)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1447)
14.12.2021 18:04:42.000 [      main] [INFO ]  com.evolit.klv.ui.part.KLVBreadcrumb     - createBreadcrumb()
14.12.2021 18:04:42.010 [      main] [INFO ]  c.e.klv.ui.part.utils.ResourceUtils      - getImage(name=arrow_right.png) using the ResourceManager
18:04:46.425;IMPORT_REGISTRATION;importedSR={com.evolit.klv.service.AbrechnungServiceInterface, com.evolit.klv.service.AnwenderEinstellungServiceInterface, com.evolit.klv.service.AuthenticationServiceInterface, com.evolit.klv.service.LookupServiceInterface, com.evolit.klv.service.RechnungServiceInterface, com.evolit.klv.service.TerminalServiceInterface, com.evolit.klv.service.NebengebuehrServiceInterface, com.evolit.klv.service.ITEVorgangServiceInterface, com.evolit.klv.service.ReportingServiceInterface, com.evolit.klv.service.LogEndToEndServiceInterface, com.evolit.klv.service.AbrechnungKorrekturServiceInterface, com.evolit.klv.service.KundenServiceInterface, com.evolit.klv.service.KonzernServiceInterface}={service.intents=osgi.async, service.id=216, service.bundleid=91, service.scope=bundle, osgi.basic.timeout=1800000, service.imported.configs=[ecf.jaxrs.jersey.client], endpoint.id=http://[myserver] service.imported=org.eclipse.ecf.provider.jaxrs.client.JaxRSClientContainer$JaxRSClientRemoteService@4ca4a0c6};cID=URIID [uri=myserver];rsId=0
--Endpoint Description---
<endpoint-descriptions xmlns="http://www.osgi.org/xmlns/rsa/v1.0.0">
  <endpoint-description>
    <property name="ecf.endpoint.id.ns" value-type="String" value="ecf.namespace.jaxrs"/>
    <property name="ecf.endpoint.rsfilter" value-type="String" value="(objectClass=*)"/>
    <property name="ecf.rsvc.id" value-type="Long" value="0"/>
    <property name="endpoint.id" value-type="String" value="myserver"/>
    <property name="objectClass" value-type="String">
      <array>
        <value>com.evolit.klv.service.AbrechnungServiceInterface</value>
        <value>com.evolit.klv.service.AnwenderEinstellungServiceInterface</value>
        <value>com.evolit.klv.service.AuthenticationServiceInterface</value>
        <value>com.evolit.klv.service.LookupServiceInterface</value>
        <value>com.evolit.klv.service.RechnungServiceInterface</value>
        <value>com.evolit.klv.service.TerminalServiceInterface</value>
        <value>com.evolit.klv.service.NebengebuehrServiceInterface</value>
        <value>com.evolit.klv.service.ITEVorgangServiceInterface</value>
        <value>com.evolit.klv.service.ReportingServiceInterface</value>
        <value>com.evolit.klv.service.LogEndToEndServiceInterface</value>
        <value>com.evolit.klv.service.AbrechnungKorrekturServiceInterface</value>
        <value>com.evolit.klv.service.KundenServiceInterface</value>
        <value>com.evolit.klv.service.KonzernServiceInterface</value>
      </array>
    </property>
    <property name="osgi.basic.timeout" value-type="String" value="1800000"/>
    <property name="remote.configs.supported" value-type="String">
      <array>
        <value>ecf.jaxrs.jersey.server</value>
      </array>
    </property>
    <property name="remote.intents.supported" value-type="String">
      <array>
        <value>passByValue</value>
        <value>exactlyOnce</value>
        <value>ordered</value>
        <value>jaxrs</value>
      </array>
    </property>
    <property name="service.imported.configs" value-type="String">
      <array>
        <value>ecf.jaxrs.jersey.client</value>
      </array>
    </property>
    <property name="service.intents" value-type="String" value="osgi.async"/>
  </endpoint-description>
</endpoint-descriptions>
---End Endpoint Description

From the log it's clear (look for 18:04:46.425;IMPORT_REGISTRATION) that the ECF/JaxRS Services are started AFTER the LoginController which needs them to perform the login (search for 18:04:46.425;IMPORT_REGISTRATION)

As an example the AuthServiceInjection looks like this

    @Inject
    @Service
    private AuthenticationServiceInterface authService;

I tried to change this to

    @Service
    @Reference(cardinality = ReferenceCardinality.OPTIONAL, policyOption = ReferencePolicyOption.GREEDY)
    private AuthenticationServiceInterface authService;

but this only leeds to a nullpointer exception. Changing the OPTIONAL to ReferenceCardinality.MANDATORY doesn't help.My EDEF.xml looks like this

<?xml version="1.0" encoding="UTF-8"?>
<endpoint-descriptions xmlns="http://www.osgi.org/xmlns/rsa/v1.0.0">
    <endpoint-description>

        <!-- Properties unique to service -->

        <!--  property name="ecf.endpoint.id" value-type="String" value="http://localhost:8080x" /-->
        <!--  moved to properties file; see: https://modumind.com/2020/11/05/ecf-and-rest-improved-support-for-properties-and-profiles/-->

        <property name="objectClass" value-type="String">
            <array>
                <value>com.evolit.klv.service.AbrechnungServiceInterface</value>
                <value>com.evolit.klv.service.AnwenderEinstellungServiceInterface</value>
                <value>com.evolit.klv.service.AuthenticationServiceInterface</value>
                <value>com.evolit.klv.service.LookupServiceInterface</value>
                <value>com.evolit.klv.service.RechnungServiceInterface</value>
                <value>com.evolit.klv.service.TerminalServiceInterface</value>
                <value>com.evolit.klv.service.NebengebuehrServiceInterface</value>
                <value>com.evolit.klv.service.ITEVorgangServiceInterface</value>
                <value>com.evolit.klv.service.ReportingServiceInterface</value>
                <value>com.evolit.klv.service.LogEndToEndServiceInterface</value>
                <value>com.evolit.klv.service.AbrechnungKorrekturServiceInterface</value>
                <value>com.evolit.klv.service.KundenServiceInterface</value>
                <value>com.evolit.klv.service.KonzernServiceInterface</value>
            </array>
        </property>

        <!--  Properties same for all services -->

        <property name="ecf.endpoint.id.ns" value-type="String" value="ecf.namespace.jaxrs" />
        <property name="endpoint.id" value-type="String" value="http://localhost:8080" />
        <property name="ecf.rsvc.id" value-type="Long" value="0" />
        <property name="ecf.endpoint.rsfilter" value-type="String" value="(objectClass=*)" />
        <property name="osgi.basic.timeout" value="1800000" />
        <property name="remote.configs.supported" value-type="String">
            <array>
                <value>ecf.jaxrs.jersey.server</value>
            </array>
        </property>

        <property name="remote.intents.supported" value-type="String">
            <array>
                <value>passByValue</value>
                <value>exactlyOnce</value>
                <value>ordered</value>
                <value>jaxrs</value>
            </array>
        </property>

        <property name="service.imported.configs" value-type="String">
            <array>
                <value>ecf.jaxrs.jersey.server</value>
            </array>
        </property>

        <property name="service.intents" value-type="String">
            <array>
                <value>osgi.async</value>
            </array>
        </property>
    </endpoint-description>
</endpoint-descriptions>

Any pointers on what else I could try to improve things?

scottslewis commented 2 years ago

I implemented all the changes but unfortunately this is still bugging us, I finally managed to get a full log/stacktrace

> > From the log it's clear (look for 18:04:46.425;IMPORT_REGISTRATION) that the ECF/JaxRS Services are started AFTER the LoginController which needs them to perform the login (search for 18:04:46.425;IMPORT_REGISTRATION) > > As an example the AuthServiceInjection looks like this > > ``` > @Inject > @Service > private AuthenticationServiceInterface authService; > ``` > > I tried to change this to > > ``` > @Service > @Reference(cardinality = ReferenceCardinality.OPTIONAL, policyOption = ReferencePolicyOption.GREEDY) > private AuthenticationServiceInterface authService; > ``` > Could you post the entire class that you are annotating with @Service and @Reference(...)? Declarative Services works somewhat differently than e4 injection (i.e. @Inject and @Service). Here is an example of a typical remote reference: https://github.com/ECF/JaxRSProviders/blob/master/examples/com.mycorp.examples.student.client/src/com/mycorp/examples/student/client/StudentServiceClient.java Note a couple of things: 1) The @Component annotation is above the class declaration. Your @Component annotation should probably *not* have immediate=true....i.e. you should simply have: @Component public class MyClass extends ... With the DS injection you can annotate a method (e.g. bindStudentService/unbindStudentService) with this markup: @Reference(policy=ReferencePolicy.DYNAMIC) void bindStudentService(StudentService service) throws Exception { Note you can do a similar thing with: @Reference(policy=ReferencePolicy.DYNAMIC) private volatile StudentService studentService; When debugging/testing I like to use the bind/unbind methods so that I can put breakpoints inside the bind/unbind methods to check that they are being called at the right time. Note the ReferencePolicy.DYNAMIC. This means that the service reference can *come and go dynamically*. This is generally needed for remote services, because they can appear/disappear at connect/disconnect...which can happen anytime. So could you provide me with all of the code for your code that uses the AuthenticationService? Also...for using DS at runtime you will need the SCR implementation in your runtime (and start it early enough...e.g. Eclipse starts it at level 2 I think).
nagelfargithub commented 2 years ago

The AuthenticationServiceInterface


public interface AuthenticationServiceInterface {
    @POST
    @Path(Endpoints.LOGIN)
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    RestResponse<AnwenderDTO> login(LoginDTO request);

    @POST
    @Path(Endpoints.LOGOUT)
    void logout();
}

Used in LoginController

@Creatable
public class LoginController {
    private static final Logger log = LoggerFactory.getLogger(LoginController.class);

    @Inject
    private ApplicationState state;

    @Inject
    @Service
    private AuthenticationServiceInterface authService;

    @Inject
    @Service
    private LookupServiceInterface lookupService;

    @Inject
    @Service
    private TerminalServiceInterface terminalService;

    @Inject
    private IEclipseContext context;

    private LoginDialog dialog;

    @PostConstruct
    public void init() {
        log.info("LoginController init");
    }

    private void loginWithApi(LoginDTO login) {
        log.info("loginWithApi userName: {}", login.getUsername());
        final RestResponse<AnwenderDTO> loginResult = callApiGetResponse(() -> authService.login(login));
                ...do stuff with the resonse
    }

    public boolean doLogin() {
        log.info("doLogin() -  starting the login dialog");
        final Shell shell = new Shell(SWT.INHERIT_NONE|SWT.ON_TOP);
        try {
            log.info("doLogin with dialog");
            dialog = new LoginDialog(shell, this::loginWithApi, this::selectTerminal);
            ContextInjectionFactory.inject(dialog, context);

            return dialog.open() == Window.OK;
        } catch(Exception e) {
            log.error("doLogin, error on creating LoginDialog", e);
            return false;
        } finally {
            shell.dispose();
        }
    }

I can confirm that we start felix.src with startlevel 2, autostart true.

scottslewis commented 2 years ago

The AuthenticationServiceInterface



public interface AuthenticationServiceInterface {
  @POST
  @Path(Endpoints.LOGIN)
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  RestResponse<AnwenderDTO> login(LoginDTO request);

  @POST
  @Path(Endpoints.LOGOUT)
  void logout();
}

This looks fine to me...i.e. using the JaxRSAnnotations.


Used in LoginController

@Creatable public class LoginController { private static final Logger log = LoggerFactory.getLogger(LoginController.class);

@Inject private ApplicationState state;

@Inject @Service private AuthenticationServiceInterface authService;

@Inject @Service private LookupServiceInterface lookupService;

@Inject @Service private TerminalServiceInterface terminalService;

@Inject private IEclipseContext context;

private LoginDialog dialog;

@PostConstruct public void init() { log.info("LoginController init"); }

private void loginWithApi(LoginDTO login) { log.info("loginWithApi userName: {}", login.getUsername()); final RestResponse loginResult = callApiGetResponse(() -> authService.login(login)); ...do stuff with the resonse }

public boolean doLogin() { log.info("doLogin() - starting the login dialog"); final Shell shell = new Shell(SWT.INHERIT_NONE|SWT.ON_TOP); try { log.info("doLogin with dialog"); dialog = new LoginDialog(shell, this::loginWithApi, this::selectTerminal); ContextInjectionFactory.inject(dialog, context);

      return dialog.open() == Window.OK;
  } catch(Exception e) {
      log.error("doLogin, error on creating LoginDialog", e);
      return false;
  } finally {
      shell.dispose();
  }

}

I believe the @Creatable, @Inject, and @Service annotations (Eclipse injections) are problematic for this use case. Here's why: AFAIK...with the Eclipse annotations @Createable, @Inject, and @Service. the injection mechanism does not handle dynamic OSGi service injection (and therefore doesn't properly handle the timing of remote services...which are dynamic). What I mean by this is that depending upon startup sequence and/or connect timing/network delays it may be that your impl gets created and initialized before the AuthenticationServiceInterface gets discovered, imported, created, and injected (which all take an unpredictable amount of time...because of network delays...and so sets up a race condition). This seems from your stack traces as if it is happening...as it appears to me that the doLogin() method (or others) might be called before the authService instance is discovered, imported, and injected. And since E4 injection does not handle such dynamics (the IAuthenticationService appearing after injection) a NPE happens as the authService is null (is this right)?

If this is right, then there are two ways that I can think of to deal with this situation.

1) Replace Eclipse/E4 injection with Declarative Services injection. As you've seen, it's possible with DS to deal with DYNAMIC services (and preventing the initialization/activation of a Component until all references have been resolved...DYNAMIC or not. This deals with the timing since basically you can wait until the discovery, import, dynamic injection has occurred.

2) Control the discovery, import, injection of your remote services yourself (i.e. in the application). That is, instead of having E4 or SCR inject the remote service...you can set things up so that the discovery, connect, import, inject is done when your app is ready for it. There are other users of ECF Remote Services that are doing this...so that they can control the app startup sequence easily in their application. It's not as difficult as it might sound, as the RemoteServiceAdmin is a service that is started automatically by standard impls of the OSGi Remote Service Admin (of which ECF is one).

I can/will help you with either of thse approaches. Overall I would recommend 1 unless you want to explicitly control the discovery, import, injection of remote services (which are dynamic and therefore not easily handled by E4 injecttion).

nagelfargithub commented 2 years ago

What I mean by this is that depending upon startup sequence and/or connect timing/network delays it may be that your impl gets created and initialized before the AuthenticationServiceInterface gets discovered, imported, created, and injected (which all take an unpredictable amount of time...because of network delays...and so sets up a race condition).

Interesting insight, only thing I don't understand: why are there network delays? This is all happening on one machine where the client gets deployed to. What kind of network requests might be involved here?

This seems from your stack traces as if it is happening...as it appears to me that the doLogin() method (or others) might be called before the authService instance is discovered, imported, and injected. And since E4 injection does not handle such d ynamics (the IAuthenticationService appearing after injection) a NPE happens as the authService is null (is this right)?

I can't tell if this is what is happening but I agree that it certainly looks like it from the stacktrace.

  1. Replace Eclipse/E4 injection with Declarative Services injection. As you've seen, it's possible with DS to deal with DYNAMIC services (and preventing the initialization/activation of a Component until all references have been resolved...DYNAMIC or not. This deals with the timing since basically you can wait until the discovery, import, dynamic injection has occurred.
  2. Control the discovery, import, injection of your remote services yourself (i.e. in the application). That is, instead of having E4 or SCR inject the remote service...you can set things up so that the discovery, connect, import, inject is done when your app is ready for it. There are other users of ECF Remote Services that are doing this...so that they can control the app startup sequence easily in their application. It's not as difficult as it might sound, as the RemoteServiceAdmin is a service that is started automatically by standard impls of the OSGi Remote Service Admin (of which ECF is one).

I can/will help you with either of thse approaches. Overall I would recommend 1 unless you want to explicitly control the discovery, import, injection of remote services (which are dynamic and therefore not easily handled by E4 injecttion).

Can you give a short overview on what would be necessary for option 2? I understand that option 1 would probably be the mor e proper thing to do but it would require quite some rewrites of existing code...

scottslewis commented 2 years ago

What I mean by this is that depending upon startup sequence and/or connect timing/network delays it may be that your impl gets created and initialized before the AuthenticationServiceInterface gets discovered, imported, created, and injected (which all take an unpredictable amount of time...because of network delays...and so sets up a race condition).

Interesting insight, only thing I don't understand: why are there network delays? This is all happening on one machine where the client gets deployed to. What kind of network requests might be involved here?

With the JaxRS/Jersey provided there is no network call during the proxy creation, import, injection...I was thinking of other providers. There is, however, still some amount of local computation having to do with proxy creation and reflection...only being able to occur after all of RSA (including Jersey itself...which is a significant codebase) is loaded+initialized.

This seems from your stack traces as if it is happening...as it appears to me that the doLogin() method (or others) might be called before the authService instance is discovered, imported, and injected. And since E4 injection does not handle such d ynamics (the IAuthenticationService appearing after injection) a NPE happens as the authService is null (is this right)?

I can't tell if this is what is happening but I agree that it certainly looks like it from the stacktrace.

  1. Replace Eclipse/E4 injection with Declarative Services injection. As you've seen, it's possible with DS to deal with DYNAMIC services (and preventing the initialization/activation of a Component until all references have been resolved...DYNAMIC or not. This deals with the timing since basically you can wait until the discovery, import, dynamic injection has occurred.
  2. Control the discovery, import, injection of your remote services yourself (i.e. in the application). That is, instead of having E4 or SCR inject the remote service...you can set things up so that the discovery, connect, import, inject is done when your app is ready for it. There are other users of ECF Remote Services that are doing this...so that they can control the app startup sequence easily in their application. It's not as difficult as it might sound, as the RemoteServiceAdmin is a service that is started automatically by standard impls of the OSGi Remote Service Admin (of which ECF is one).

I can/will help you with either of thse approaches. Overall I would recommend 1 unless you want to explicitly control the discovery, import, injection of remote services (which are dynamic and therefore not easily handled by E4 injecttion).

Can you give a short overview on what would be necessary for option 2? I understand that option 1 would probably be the mor e proper thing to do but it would require quite some rewrites of existing code...

Yes. The short story is that you can control the import of a remote service yourself through use of this service:

https://download.eclipse.org/rt/ecf/latest/javadoc/org/osgi/service/remoteserviceadmin/RemoteServiceAdmin.html

This service interface is defined by the OSGi Remote Service Admin standard, and ECF implements it. An instance of this service is created (and will be injected by DS if present and running) on start of the ECF bundle: org.eclipse.ecf.osgi.services.remoteserviceadmin.

If you wish to skip discovery, and import a remote service manually you can call: RemoteServiceAdmin.importService(EndpointDescription).

To explain this a little bit: RSA OSGi spec has the concept of a TopologyManager. The topology manager receives notifications from discovery mechanism (whether edef file, network discovery, etc) and in response to 'discovered' notifications creates a instance of EndpointDescription (from the edef file) and calls RemoteServiceAdmin.importService(EndpointDescription). There is more information about this (specified) architecture here:

https://wiki.eclipse.org/EIG:Remote_Services_Admin

and in the spec itself: https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.remoteserviceadmin.html

In short instead of using file-based discovery you can simply:

1) Have DS inject the RemoteServiceAdmin instance into a component as a required dependency 2) When ready and appropriate (i.e. everything else in your app is ready), a) Read your edef using an ECF class: EndpointDescriptionReader (which reads xml and returns and EndpointDescription) b) Call RemoteServiceAdmin.importService(your EndpointDescription created in 2a)

Unfortunately I don't have an example of this in this repository but there are other ECF consumers that do this.

nagelfargithub commented 2 years ago

Thank you for the input, I'm not quite sure if manual lookup is the proper way for us to go, I'll have to take a closer look into the stuff you described. I'll report back as soon as I have more input/questions/results. Also, we are using the (additional) @Service annotation (see e.g. http://blog.vogella.com/2017/03/15/osgi-declarative-services-news-in-eclipse-oxygen/) which should help to avoid issues as we are seeing them. Patrick at Modumind (https://www.modumind.com/2020/05/19/eclipse-rcp-and-rest-an-introduction/) also describes a combination of @Inject and @Service instead of a DS Facade. I contacted both Dirk and Patrick via email and pointed them to this issue, perhaps we can find a solution after all.

fipro78 commented 2 years ago

Hi, sorry but the thread is pretty long and I can't go through it in detail. From a quick look the mistake is to mix the DS injection with the E4 injection in a critical lifecycle process. The @Service annotation is intended to improve the injection of OSGi services in the Eclipse layer. But although Eclipse service injection supports dynamics, the two injection mechanisms do not share the same activation lifecycle.

To make it short, the issue is not related to dynamic service references. The issue is related to mandatory service references and different activation patterns.

To give a bit more details about your issue:

Looking at your LoginController that means the Eclipse injection mechanism tries to create the instance without checking the satisfied state (of course as Eclipse injection does not know that concept). The exceptions are then thrown because the service instances you want to inject via @Service do not exist at the time the LoginController instance is created. That would only work if you mark all the referenced services via @Optional, which is not really what you want, as you need the other services to make the LoginController work.

My recommendation would be:

  1. Make the LoginController an OSGi service and use @Reference to define the dependencies to other services. This way the LoginController gets activated and becomes available only if all referenced services are available
  2. The place where the LoginController is used can use the Eclipse injection via @Service, but I would suggest to use method injection here and mark it as @Optional. This way the consumer of the LoginController is not blocked or will throw exceptions at creation time. But it of course can not work until a LoginController is available. Then you need to implement a mechanism that checks if a LoginController is set before it is used. If it is not available yet it needs to wait until the LoginController service becomes available. Then in the method to which it is injected can trigger the further processing.
modular-mind commented 2 years ago

Just finished reviewing all of this. In short, I agree with @fipro78 that the LoginController should be a DS component with references to the JAX-RS services.

@nagelfargithub You mentioned in an email the suggestion in my blog post that the @Service annotation was preferable to a DS facade. In that case I was trying to avoid having to create a facade for every JAX-RS service, especially when there might be only one service to wrap. But in this case you actually have a valid aggregation service (LoginController) so it definitely makes sense to go that way.

Of course we still have an issue with even a single JAX-RS service injected with the @Service interface. Just to check, do you have "Bundle-ActivationPolicy: lazy" in your MANIFEST.MF? I've had issues when this was not set.

scottslewis commented 2 years ago

Thanks to @fipro78 and @modular-mind for diagnosis and suggestions. My knowledge of Eclipse injection is so much less than it is for DS that I was taking a shot in the dark about dynamics handling...but at least according to Dirk I wasn't too far off! (less sophisticated reference mgmt and activation).

fipro78 commented 2 years ago

Well also eclipse injection supports some kind of reference resolution and activation. But only in its own context. If the services would be managed by the Eclipse injection it would create the instances once requested. That is the same in most injection frameworks. The problem is that on the one side you have eclipse injection managed classes and on the other side osgi scr managed services. And there is no bridge that would connect the two injection containers on instance creation. Sorry if my explanation lead into the direction that the Eclipse injection is not a good injection framework. IMHO it is working very good, but some different concepts than with osgi ds

scottslewis commented 2 years ago

No offense to Eclipse injection intended. Is there a document describing all the specifics of dynamics, lifecycle, etc for Eclipse Injection somewhere?

fipro78 commented 2 years ago

No offense detected. :-)

Just wanted to clarify that the issue is the mixture of two injection frameworks, not the one or the other framework itself. With the @Service annotation we wanted to make the integration better as the simple service injection has its problems, but it does not solve all combination issues, especially not with regards to the lifecycle. With OSGi DS for example the bundle starting order problems can be solved as it is integrated in the OSGi framework. The Eclipse injection framework is not capable to do this.

I know most of the Eclipse injection basics from books, the code and experience. I think the following articles describe it the best:

https://wiki.eclipse.org/Eclipse4/RCP/Dependency_Injection https://www.google.com/amp/s/eclipsesource.com/blogs/tutorials/eclipse-4-e4-tutorial-part-4-dependency-injection-basics/ https://www.vogella.com/tutorials/Eclipse4ContextUsage/article.html

nagelfargithub commented 2 years ago

@modular-mind yes, bundle-activation is set to lazy.

Thanks everyone for the valuable input so far, let me try to do a summary:

Does that sound about right?

As for "fixing" things my summary would be: Make the LoginController itself an OSGi service and use @Reference to define the dependencies to other services. This way the LoginController gets activated and becomes available only if all referenced services are available The place where the LoginController is used can use the Eclipse injection via @Service, but should use method injection and be marked @Optional. This way the consumer of the LoginController is not blocked or will throw exceptions at creation time. For that to work I need to implement a mechanism that checks if a LoginController is set before it is used. If it is not available yet it needs to wait until the LoginController service becomes available. Then in the method to which it is injected can trigger the further processing.

Any additional comments on that? What would a waiting mechanism for something like that even look like? Literal Thread.sleep?

Thanks again for anyone giving their opinion, highly appreciated.

fipro78 commented 2 years ago

Well I still don't know how your consumer of the LoginController looks like. But assuming it is some sort of dialog that opens so a user can enter the credentials. In that case I would by default open the dialog and show a text like "Establishing connection" by default. The method that is used for the injection of the LoginController would replace the text with the input fields and the OK button once the injection of the LoginController is triggered. In such a scenario there is no need for a waiting mechanism. The whole mechanism would be reactive. Only for UX cases you would add some waiting mechanism to show an error if the injection of the LoginController does not happen in a specific time frame.

BTW, the dynamic method injection and re-injection is one of the features provided by the Eclipse injection framework that you don't find typically in other injection frameworks. ;) Of course OSGi DS also supports dynamic reinjection.

nagelfargithub commented 2 years ago

You're basically right but I'm happy to show our current setup:

First of all, we have a Lifecyclemanager, triggered via plugin.xml

public class LifeCycleManager {
    private static final Logger log = LoggerFactory.getLogger(LifeCycleManager.class);

    @Inject
    private LoginController loginController;

    @Inject
    private  AnwenderEinstellungCache anwenderEinstellungCache;

    @Inject
    @Service
    private AnwenderEinstellungServiceInterface anwenderEinstellungServiceInterface;
    @Inject
    private ApplicationState state;
    @Inject
    private UpdateManager updateManager;

    @Inject
    @Translation
    KLVMessages messages;

    @PostConstruct
    public void init() {
        log.info("LifeCycleManager init");
    }

    @PostContextCreate
    void postContextCreate(IApplicationContext appContext, IEclipseContext context, IEventBroker eventBroker) {
        log.info("------------------------------");
        log.info("       Starting KLV 4.0       ");
        log.info("------------------------------");
        logSystemInformation();
        log.info("check for updates...");
        boolean updateDone = updateManager.performAutoUpdate();
        //close the splashscreen
        appContext.applicationRunning();
        if(updateDone) { 
            log.info("update was performed");
            eventBroker.subscribe(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE, new ApplicationUpdateListener(context));
            final Shell shell = new Shell(SWT.INHERIT_NONE);
            MessageDialog.openInformation(shell, messages.label_restart, messages.msg_restart);
        } else {
            log.info("no update necessary");
        }
        if(!updateDone) {
            if (!loginController.doLogin()) {
                log.info("------------------------------");
                log.info("User canceled the login exit the application");
                log.info("------------------------------");
                // use system.exit because we don't have a workbench yet
                System.exit(0);
            } else {
                log.info("Login successful");
                initAnwenderEinstellungen(state.getAnwender());
            }
        } else {
            log.debug("let the eventhandler restart the application");
        }
    }

    private void logSystemInformation() {
        log.info("java.version: {}", System.getProperty("java.version"));
        log.info("java.class.version: {}", System.getProperty("java.class.version"));
        log.info("java.home: {}", System.getProperty("java.home"));
        log.info("java.class.path: {}", System.getProperty("java.class.path"));
        log.info("user.dir: {}", System.getProperty("user.dir"));
        log.info("user.home: {}", System.getProperty("user.home"));
        log.info("isTest: {}", System.getProperty("com.evolit.klv.test", "false"));
        log.info("repository URL: {}", System.getProperty("repository"));       
        Bundle bundle = FrameworkUtil.getBundle(getClass());
        if (bundle != null) {
            log.info("version: {}", bundle.getVersion().toString());
        } else {
            log.info("bundle version nicht verfügbar");
        }
    }

    @ProcessAdditions
    public void processAdditions() {
        log.info("processAdditions()");
        if (ResourceUtils.loadFont(KLVFontIcons.ICON_FONT_PATH)) {
            log.info("Icon Font {} successfully loaded", KLVFontIcons.ICON_FONT_PATH);
        } else {
            log.error("Icon Font {} could not be loaded", KLVFontIcons.ICON_FONT_PATH);
        }
    }

    private void initAnwenderEinstellungen(AnwenderDTO anwender) {
        log.info("initAnwenderEinstellungen() {}", anwender);
        BusyIndicator.showWhile(Display.getDefault(), () -> {
            final RestResponse<List<AnwenderEinstellungDTO>> res = callApiGetResponse(() -> 
            anwenderEinstellungServiceInterface.listEinstellungen(anwender.getId()));
            if (res.hasError()) {
                log.error(res.getError().getMessage());
                return;
            }
            if (res.getData()!=null) {  //empty data is mapped to null
                anwenderEinstellungCache.setSettings(res.getData());
            }

            log.info("user settings initialized!");
        });
    }

    @PreSave
    public void preSave(AbrechnungViewSizeService abrechnungViewSizeService) {
        //Anwender might be null on automatic restart
        if(state.getAnwender()==null) {
            return;
        }
        log.info("preSave()");
        abrechnungViewSizeService.preSave();

    }

}

The LoginController

@Creatable
public class LoginController {
    private static final String DIRECT_AUTH_DELIMITER = ":";

    private static final String DIRECT_AUTH_SYSTEM_PROPERTY = "com.evolit.klv.auth.direct";

    private static final Logger log = LoggerFactory.getLogger(LoginController.class);

    @Inject
    private ApplicationState state;

    @Inject
    @Service
    private AuthenticationServiceInterface authService;

    @Inject
    @Service
    private LookupServiceInterface lookupService;

    @Inject
    @Service
    private TerminalServiceInterface terminalService;

    @Inject
    private IEclipseContext context;

    private LoginDialog dialog;

    @PostConstruct
    public void init() {
        log.info("LoginController init");
    }

    private void loginWithApi(LoginDTO login) {
        log.info("loginWithApi userName: {}", login.getUsername());
        final RestResponse<AnwenderDTO> loginResult = callApiGetResponse(() -> authService.login(login));
        if (loginResult.hasError()) {
            log.info("Login failed.", loginResult.getError());
            this.dialog.loginFailed(loginResult.getError().getStatus());
            return;
        }
        state.setAnwender(loginResult.getData());
        log.info("Login successful for anwender {}. Fetching terminals...", loginResult.getData());

        final RestResponse<List<TerminalDTO>> terminalResult = callApiGetResponse(() -> terminalService.getTerminalsForLoggedInAnwender());
        if (terminalResult.hasError()) {
            this.dialog.loginFailed(terminalResult.getError().getStatus());
            return;
        }

        if (terminalResult.getData().size() == 1) {
            log.debug("Only one terminal found for user, select this terminal.");
            selectTerminal(terminalResult.getData().get(0));
        } else {
            log.debug("Multiple terminals found for user, user must select one of {} terminals", terminalResult.getData().size());
            dialog.chooseTerminals(terminalResult.getData());
        }
    }

    private boolean loadAndSetAdditionalData(TerminalDTO terminal) {
        final Optional<TerminalLookupDTO> terminalLookupResult = callApiGetData(() -> this.lookupService.getTerminalLookup(terminal.getId()));
        if (!terminalLookupResult.isPresent()) {
            log.error("Could not fetch lookup for user and terminal.");
            return false;
        }
        state.setTerminalLookup(terminalLookupResult.get());
        RestResponse<GeneralLookupDTO> generalLookupResponse = lookupService.getGeneralLookup();
        if(generalLookupResponse.hasError()) {
            log.error("unexpected error reading GeneralLookup");
            return false;
        }
        state.setGeneralLookup(generalLookupResponse.getData());
        return true;
    }

    private void selectTerminal(TerminalDTO terminal) {
        log.info("Terminal  selected {}", terminal);

        if (loadAndSetAdditionalData(terminal)) {
            state.setTerminal(terminal);
            this.dialog.loginSuccess();
        } else {
            state.setAnwender(null);
            this.dialog.loadAdditionalDataFailed();
        }
    }

    private Optional<String[]> parseDirectAuthProperty(String directAuthProp) {
        return Optional.ofNullable(directAuthProp)
                .map(s -> s.split(DIRECT_AUTH_DELIMITER))
                .filter(s -> s.length == 3);
    }

    private boolean doDirectLogin(String[] directAuth) {
        log.info("doDirectLogin");
        if (directAuth.length != 3) {
            return false;
        }
        final LoginDTO login = new LoginDTO(directAuth[0], directAuth[1]);
        final long terminalId = Long.parseLong(directAuth[2]);

        boolean successful = callApiGetData(() -> authService.login(login))
            .flatMap(anwender -> {
                state.setAnwender(anwender);
                return callApiGetData(() -> terminalService.getTerminalsForLoggedInAnwender());
            })
            .flatMap(terminals -> terminals.stream()
                    .filter(t -> t.getId() == terminalId)
                    .findFirst())
            .map(terminal -> {
                // select terminal
                state.setTerminal(terminal);
                return loadAndSetAdditionalData(terminal);
            })
            .orElse(false);

        if (!successful) {
            log.error("Direct auth failed for login {}, and terminalId {}", login, terminalId);
        } else {
            log.debug("direct auth successful");        
        }
        return successful;
    }

    public boolean doLogin() {
        log.info("doLogin() -  starting the login dialog");
        Optional<String[]> directAuth = parseDirectAuthProperty(System.getProperty(DIRECT_AUTH_SYSTEM_PROPERTY));
        if (directAuth.isPresent()) {
            log.info("attempting direct login");
            return doDirectLogin(directAuth.get());
        }
        final Shell shell = new Shell(SWT.INHERIT_NONE|SWT.ON_TOP);
        try {
            log.info("doLogin with dialog");
            dialog = new LoginDialog(shell, this::loginWithApi, this::selectTerminal);
            ContextInjectionFactory.inject(dialog, context);

            return dialog.open() == Window.OK;
        } catch(Exception e) {
            log.error("doLogin, error on creating LoginDialog", e);
            return false;
        } finally {
            shell.dispose();
        }
    }
}

The LoginDialog

public class LoginDialog extends KLVTitleAreaDialog {

    private static final Logger log = LoggerFactory.getLogger(LoginDialog.class);

    @Inject
    @Translation
    private KLVMessages messages;

    @Inject
    private ApplicationState state;

    private final Consumer<LoginDTO> handleLogin;
    private final Consumer<TerminalDTO> handleTerminalSelected;

    private Text loginTextField;
    private Text passwordTexField;
    private Composite terminalsForm;
    private ComboViewer terminalsComboSelect;

    public LoginDialog(Shell shell, Consumer<LoginDTO> handleLogin, Consumer<TerminalDTO> handleTerminalSelected) {
        super(shell);
        this.handleLogin = handleLogin;
        this.handleTerminalSelected = handleTerminalSelected;
    }

    public void chooseTerminals(List<TerminalDTO> terminals) {
        this.getShell().getDisplay().asyncExec(() -> {
            setMessage(messages.message_logindialog_choose_terminal, IMessageProvider.INFORMATION);
            buttonBar.setEnabled(true);
            terminalsComboSelect.setInput(terminals);
            terminalsForm.setVisible(true);
            terminalsComboSelect.getCombo().setFocus();
            getShell().setCursor(null);
        });
    }

    @Override
    public void create() {
        super.create();
        setTitle(messages.title_logindialog);
        setMessage(messages.message_logindialog_info, IMessageProvider.INFORMATION);
    }   

    public void loginSuccess() {
        this.getShell().getDisplay().asyncExec(() -> {
            super.okPressed();      
        });
    }

    public void loginFailed(int status) {
        this.getShell().getDisplay().asyncExec(() -> {
            loginTextField.setFocus();
            if (Response.Status.UNAUTHORIZED.getStatusCode() == status) {
                setMessage(messages.message_logindialog_401, IMessageProvider.ERROR);
            } else {
                setMessage(messages.message_logindialog_error, IMessageProvider.ERROR);
            }
        });
    }

    public void loadAdditionalDataFailed() {
        this.getShell().getDisplay().asyncExec(() -> {
            loginTextField.setFocus();
            setMessage(messages.message_logindialog_load_data_error, IMessageProvider.ERROR);
            terminalsForm.setVisible(false);
        });
    }

    protected void setEnabled(boolean enabled) {
        loginTextField.setEnabled(enabled);
        passwordTexField.setEnabled(enabled);
        buttonBar.setEnabled(enabled);
    }

    @Override
    protected void okPressed() {
        ProgressMonitorDialog dialog = new ProgressMonitorDialog(this.getShell());
        try {
            dialog.run(false, false, new IRunnableWithProgress(){
                public void run(IProgressMonitor monitor) {
                    monitor.beginTask(messages.message_logindialog_in_progress, IProgressMonitor.UNKNOWN);
                    if (!terminalsForm.isVisible()) {
                        // login
                        final String login = loginTextField.getText();
                        state.setLogin(login);
                        handleLogin.accept(new LoginDTO(login, passwordTexField.getText()));
                    } else {
                        // terminal select
                        IStructuredSelection selection = (IStructuredSelection) terminalsComboSelect.getSelection();
                        TerminalDTO selected = (TerminalDTO) selection.getFirstElement();
                        if (selected == null) {
                            setMessage(messages.message_logindialog_choose_terminal_error, IMessageProvider.ERROR);
                        } else {
                            handleTerminalSelected.accept(selected);
                        }
                    }                   
                    monitor.done();
                }
            });
        } catch (InvocationTargetException | InterruptedException e) {
            log.error("unexpected error during login", e);
            setMessage(messages.message_logindialog_error, IMessageProvider.ERROR);
        }       
    }

    @Override
    protected Control createDialogArea(Composite parent) {
        final Composite area = (Composite) super.createDialogArea(parent);
        Composite formContainer = new Composite(area, SWT.NONE);
        formContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        final GridLayout layout = new GridLayout(2, false);
        formContainer.setLayout(layout);
        createLogin(formContainer);
        createPassword(formContainer);
        createTerminalSelect(area);
        return area;
    }

    private void createLogin(Composite container) {
        final Label lblLogin = new Label(container, SWT.NONE);
        lblLogin.setText(messages.label_login);

        final GridData dataLogin = new GridData();
        dataLogin.grabExcessHorizontalSpace = true;
        dataLogin.horizontalAlignment = GridData.FILL;

        loginTextField = new Text(container, SWT.BORDER);
        loginTextField.setLayoutData(dataLogin);
        final String login = state.getLogin();
        if (login != null) {
            loginTextField.setText(login);
        }
    }

    private void createPassword(Composite container) {
        final Label lblPassword = new Label(container, SWT.NONE);
        lblPassword.setText(messages.label_password);

        final GridData dataPassword = new GridData();
        dataPassword.grabExcessHorizontalSpace = true;
        dataPassword.horizontalAlignment = GridData.FILL;
        passwordTexField = new Text(container, SWT.BORDER | SWT.PASSWORD);
        passwordTexField.setLayoutData(dataPassword);
    }

    private void createTerminalSelect(Composite area) {
        terminalsForm = new Composite(area, SWT.NONE);
        terminalsForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        final GridLayout layout = new GridLayout(2, false);
        terminalsForm.setLayout(layout);
        Label label = new Label(terminalsForm, SWT.NONE);
        label.setText(messages.label_terminal);

        final GridData layoutData = new GridData();
        layoutData.grabExcessHorizontalSpace = true;
        layoutData.horizontalAlignment = GridData.FILL;

        terminalsComboSelect = new ComboViewer(terminalsForm, SWT.READ_ONLY);
        terminalsComboSelect.getCombo().setLayoutData(layoutData);
        terminalsComboSelect.setContentProvider(ArrayContentProvider.getInstance());
        terminalsComboSelect.setLabelProvider(new LabelProvider() {
            @Override
            public String getText(Object element) {
                if (element instanceof TerminalDTO) {
                    TerminalDTO terminal = (TerminalDTO) element;
                    return terminal.getBezeichnung();
                }
                return super.getText(element);
            }
        });
        terminalsForm.setVisible(false);
    }

    @Override
    protected String getOkButtonLabelText() {
        return messages.button_anmelden;
    }

    @Override
    protected String getCancelButtonLabelText() {
        return messages.button_abbrechen;
    }

    @Override
    protected String getShellName() {
        return messages.shellname_login;
    }

    @Override
    protected String getShellImagePath() {
        return KLVFontIcons.SHELL_FAVICON;
    }

}

After the christmas holidays I'll try to take all your suggestions into account, rework the Login and let you know about the results.

fipro78 commented 2 years ago

I would suggest to redesign the startup process and the service usage. The complexity is very high, especially caused by the mixture of different injections, services and even REST services. I am not able to review this in short as the whole process needs to be clarified, when what should happen and how the dependency chain of services looks like. Not a trivial thing to solve in that setup

scottslewis commented 2 years ago

FWIW I agree with Dirk's advise about redesigning (or at least reviewing/clarifying) the service usage.

I'll say two positive things about DS/SCR/OSGi Services that pushed us (ECF) to support the OSGi Remote Services/RSA standard...and as a result the other standards around OSGi Services:

Since the as Dirk says SCR is integrated with OSGi services (everything is via the service registry), which in is linked to the bundle lifecycle (only active bundle can register or consume services), there are a number of ways available to help deal with service-level dependencies (e.g. manifest meta-data like 'Require-Capability', component and bundle-level dependency resolution (optional, required, etc) and activation/deactivation, etc) without resorting to start levels.

Another advantage (IMHO) is that since these mechanisms are standardized/specified, and in most cases multiple impls exist, they can be used in multiple contexts (e.g. servers like Karaf, Websphere, Felix, etc). Without (much) concern about inconsistent behavior across runtimes.

Good Holidays to Everyone. Please Stay Safe.

nagelfargithub commented 2 years ago

So, after quite some time my update, I hope everyone enjoyed their holidays and is save and (mostly) sane.

I did major refactoring work and changed basically everything that happens in LifecycleManager and LoginController. The LifecycleManager now has only a singular (Inject)dependency and that is to LoginController. The LoginController still uses services but I switched them to declarative services. Since implementing these changes I haven't seen any startup issues (so far) so I cautiously declare this "fixed".

Interesting sidenote: on some client starts it takes multiple seconds(!) for the services to be "ready" so this is not just a racecondition in the milliseconds range...an example log for anyone that is interested

07.02.2022 09:44:25.203 [      main] [INFO ]  com.evolit.klv.ui.LifeCycleManager       - no update necessary
07.02.2022 09:44:25.203 [      main] [INFO ]  com.evolit.klv.ui.login.LoginController  - doLogin() -  starting the login process
07.02.2022 09:44:25.203 [      main] [INFO ]  com.evolit.klv.ui.login.LoginController  - checkLoginServicesReady()
07.02.2022 09:44:25.352 [dalContext] [INFO ]  com.evolit.klv.ui.login.LoginController  - login services not yet ready, waiting...
07.02.2022 09:44:26.358 [dalContext] [INFO ]  com.evolit.klv.ui.login.LoginController  - login services not yet ready, waiting...
07.02.2022 09:44:27.373 [dalContext] [INFO ]  com.evolit.klv.ui.login.LoginController  - login services not yet ready, waiting...
07.02.2022 09:44:28.389 [dalContext] [INFO ]  com.evolit.klv.ui.login.LoginController  - login services not yet ready, waiting...
07.02.2022 09:44:29.404 [dalContext] [INFO ]  com.evolit.klv.ui.login.LoginController  - login services not yet ready, waiting...
09:44:29.771;IMPORT_REGISTRATION;importedSR={com.evolit.klv.service.AbrechnungServiceInterface, com.evolit.klv.service.AnwenderEinstellungServiceInterface, com.evolit.klv.service.AuthenticationServiceInterface, com.evolit.klv.service.LookupServiceInterface, com.evolit.klv.service.RechnungServiceInterface, com.evolit.klv.service.TerminalServiceInterface, com.evolit.klv.service.NebengebuehrServiceInterface, com.evolit.klv.service.ITEVorgangServiceInterface, com.evolit.klv.service.ReportingServiceInterface, com.evolit.klv.service.LogEndToEndServiceInterface, com.evolit.klv.service.AbrechnungKorrekturServiceInterface, com.evolit.klv.service.KundenServiceInterface, com.evolit.klv.service.KonzernServiceInterface}={service.intents=osgi.async, service.id=161, service.bundleid=91, service.scope=bundle, osgi.basic.timeout=1800000, service.imported.configs=[ecf.jaxrs.jersey.client], endpoint.id=[removed] service.imported=org.eclipse.ecf.provider.jaxrs.client.JaxRSClientContainer$JaxRSClientRemoteService@7ad4bf4a};cID=URIID [uri=[removed]];rsId=0
--Endpoint Description---
<endpoint-descriptions xmlns="http://www.osgi.org/xmlns/rsa/v1.0.0">
  <endpoint-description>
    <property name="ecf.endpoint.id.ns" value-type="String" value="ecf.namespace.jaxrs"/>
    <property name="ecf.endpoint.rsfilter" value-type="String" value="(objectClass=*)"/>
    <property name="ecf.rsvc.id" value-type="Long" value="0"/>
    <property name="endpoint.id" value-type="String" value="[removed]"/>
    <property name="objectClass" value-type="String">
      <array>
        <value>com.evolit.klv.service.AbrechnungServiceInterface</value>
        <value>com.evolit.klv.service.AnwenderEinstellungServiceInterface</value>
        <value>com.evolit.klv.service.AuthenticationServiceInterface</value>
        <value>com.evolit.klv.service.LookupServiceInterface</value>
        <value>com.evolit.klv.service.RechnungServiceInterface</value>
        <value>com.evolit.klv.service.TerminalServiceInterface</value>
        <value>com.evolit.klv.service.NebengebuehrServiceInterface</value>
        <value>com.evolit.klv.service.ITEVorgangServiceInterface</value>
        <value>com.evolit.klv.service.ReportingServiceInterface</value>
        <value>com.evolit.klv.service.LogEndToEndServiceInterface</value>
        <value>com.evolit.klv.service.AbrechnungKorrekturServiceInterface</value>
        <value>com.evolit.klv.service.KundenServiceInterface</value>
        <value>com.evolit.klv.service.KonzernServiceInterface</value>
      </array>
    </property>
    <property name="osgi.basic.timeout" value-type="String" value="1800000"/>
    <property name="remote.configs.supported" value-type="String">
      <array>
        <value>ecf.jaxrs.jersey.server</value>
      </array>
    </property>
    <property name="remote.intents.supported" value-type="String">
      <array>
        <value>passByValue</value>
        <value>exactlyOnce</value>
        <value>ordered</value>
        <value>jaxrs</value>
      </array>
    </property>
    <property name="service.imported.configs" value-type="String">
      <array>
        <value>ecf.jaxrs.jersey.client</value>
      </array>
    </property>
    <property name="service.intents" value-type="String" value="osgi.async"/>
  </endpoint-description>
</endpoint-descriptions>
---End Endpoint Description
07.02.2022 09:44:30.426 [      main] [INFO ]  com.evolit.klv.ui.login.LoginController  - loginServices are ready

Thanks everyone for the awesome and detailed input, highly appreciated!