two-slices icon indicating copy to clipboard operation
two-slices copied to clipboard

[mac] Provider com.sshtools.twoslices.impl.SWTToaster$Service not found

Open avently opened this issue 1 year ago • 6 comments

Hello. One of users has this exception on Mac arm64 on version 0.9.3. No such exception happened in 0.9.0-SNAPSHOT:

java.util.ServiceConfigurationError: com.sshtools.twoslices.ToasterService: Provider com.sshtools.twoslices.impl.SWTToaster$Service not found
	at java.base/java.util.ServiceLoader.fail(Unknown Source)
	at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.nextProviderClass(Unknown Source)
	at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(Unknown Source)
	at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(Unknown Source)
	at java.base/java.util.ServiceLoader$2.hasNext(Unknown Source)
	at java.base/java.util.ServiceLoader$3.hasNext(Unknown Source)
	at com.sshtools.twoslices.ToasterFactory$ServicesToasterFactory.toaster(ToasterFactory.java:56)
	at com.sshtools.twoslices.ToastBuilder.toast(ToastBuilder.java:513)
	at chat.simplex.common.model.NtfManager.displayNotificationViaLib(NtfManager.desktop.kt:113)
	at chat.simplex.common.model.NtfManager.displayNotification(NtfManager.desktop.kt:87)
	at chat.simplex.common.platform.AppCommon_desktopKt$initApp$1.displayNotification(AppCommon.desktop.kt:21)
	at chat.simplex.common.platform.NtfManager.displayNotification$default(NtfManager.kt:99)
	at chat.simplex.common.platform.NtfManager.notifyContactConnected(NtfManager.kt:20)
	at chat.simplex.common.model.ChatController.processReceivedMsg(SimpleXAPI.kt:1711)
	at chat.simplex.common.model.ChatController.access$processReceivedMsg(SimpleXAPI.kt:349)
	at chat.simplex.common.model.ChatController$startReceiver$1$finishedWithoutTimeout$1.invokeSuspend(SimpleXAPI.kt:483)
	at chat.simplex.common.model.ChatController$startReceiver$1$finishedWithoutTimeout$1.invoke(SimpleXAPI.kt)
	at chat.simplex.common.model.ChatController$startReceiver$1$finishedWithoutTimeout$1.invoke(SimpleXAPI.kt)
	at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturnIgnoreTimeout(Undispatched.kt:72)
	at kotlinx.coroutines.TimeoutKt.setupTimeout(Timeout.kt:148)
	at kotlinx.coroutines.TimeoutKt.withTimeoutOrNull(Timeout.kt:104)
	at chat.simplex.common.model.ChatController$startReceiver$1.invokeSuspend(SimpleXAPI.kt:482)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.internal.ScopeCoroutine.afterResume(Scopes.kt:28)
	at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:99)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
	at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:111)
	at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:99)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:585)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:802)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:706)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:693)

Do you have any idea why it happens?

avently avatar Mar 26 '24 12:03 avently

I confirm this is a problem in Mac.

Simplest code example as follows:

import com.sshtools.twoslices.Toast;
import com.sshtools.twoslices.ToastType;

Toast.toast(ToastType.INFO, "Information", "Here is some information you cannot do without.");

Error that was experienced:

Exception in thread "main" java.lang.IllegalStateException: java.util.ServiceConfigurationError: com.sshtools.twoslices.ToasterService: Provider com.sshtools.twoslices.impl.SWTToaster$Service not found
	at org.springframework.boot.SpringApplication.handleRunFailure(SpringApplication.java:825)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:344)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343)
	at com.maduranga.commander.CommanderApplication.main(CommanderApplication.java:10)
Caused by: java.util.ServiceConfigurationError: com.sshtools.twoslices.ToasterService: Provider com.sshtools.twoslices.impl.SWTToaster$Service not found
	at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:593)
	at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.nextProviderClass(ServiceLoader.java:1219)
	at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1228)
	at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(ServiceLoader.java:1273)
	at java.base/java.util.ServiceLoader$2.hasNext(ServiceLoader.java:1309)
	at java.base/java.util.ServiceLoader$3.hasNext(ServiceLoader.java:1393)
	at com.sshtools.twoslices.ToasterFactory$ServicesToasterFactory.toaster(ToasterFactory.java:56)
	at com.sshtools.twoslices.ToastBuilder.toast(ToastBuilder.java:513)
	at com.sshtools.twoslices.Toast.toast(Toast.java:70)
	at com.maduranga.commander.fileops.Finder.find(Finder.java:65)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.springframework.shell.command.invocation.InvocableShellMethod.doInvoke(InvocableShellMethod.java:306)
	at org.springframework.shell.command.invocation.InvocableShellMethod.invoke(InvocableShellMethod.java:232)
	at org.springframework.shell.command.CommandExecution$DefaultCommandExecution.evaluate(CommandExecution.java:227)
	at org.springframework.shell.Shell.evaluate(Shell.java:248)
	at org.springframework.shell.Shell.run(Shell.java:159)
	at org.springframework.shell.jline.InteractiveShellRunner.run(InteractiveShellRunner.java:73)
	at org.springframework.shell.DefaultShellApplicationRunner.run(DefaultShellApplicationRunner.java:65)
	at org.springframework.boot.SpringApplication.lambda$callRunner$4(SpringApplication.java:786)
	at org.springframework.util.function.ThrowingConsumer$1.acceptWithException(ThrowingConsumer.java:83)
	at org.springframework.util.function.ThrowingConsumer.accept(ThrowingConsumer.java:60)
	at org.springframework.util.function.ThrowingConsumer$1.accept(ThrowingConsumer.java:88)
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:798)
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:786)
	at org.springframework.boot.SpringApplication.lambda$callRunners$3(SpringApplication.java:774)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
	at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:357)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
	at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:774)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:341)

Dependancy:

		<dependency>
			<groupId>com.sshtools</groupId>
			<artifactId>two-slices</artifactId>
			<version>0.9.3</version>
		</dependency>

Have you already found any solutions or is there anything the users may be doing wrong here?

madukan avatar May 07 '24 18:05 madukan

This happened because SWT support was moved to a separate module two-slices-swt in order to make it possible for two-slices to be fully JPMS compliant. SWT itself is utterly incompatible with JPMS due to its module naming scheme.

If your application is just a simple classpath based application, all you should need to do is add ...

<dependency>
	<groupId>com.sshtools</groupId>
	<artifactId>two-slices-swt</artifactId>
	<version>0.9.3</version>
</dependency>

I had made a mistake a left the service definition in the wrong module, but I think the only bad effects of this would be the less than helpful error above. This has been fixed for 0.9.4-SNAPSHOT.

brett-smith avatar Jul 09 '24 21:07 brett-smith

In MacOS Sonoma 14.5, issue still happening. I suspect if the ScriptEngine is still used this way in new versions, and if that's the case for this error. When this error comes the Notifications don't work as well.

ScriptEngineManager providers.next(): javax.script.ScriptEngineFactory: Provider apple.applescript.AppleScriptEngineFactory not found
ScriptEngineManager providers.next(): javax.script.ScriptEngineFactory: Provider apple.applescript.AppleScriptEngineFactory not found
ScriptEngineManager providers.next(): javax.script.ScriptEngineFactory: Provider apple.applescript.AppleScriptEngineFactory not found
2024-07-10T07:21:09.481+10:00  INFO 273 --- [NotificationsTester] [           main] .s.b.a.l.ConditionEvaluationReportLogger : 

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2024-07-10T07:21:09.490+10:00 ERROR 273 --- [NotificationsTester] [           main] o.s.boot.SpringApplication               : Application run failed

java.util.ServiceConfigurationError: com.sshtools.twoslices.ToasterService: Provider com.sshtools.twoslices.impl.SWTToaster$Service not found
	at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:593) ~[na:na]
	at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.nextProviderClass(ServiceLoader.java:1219) ~[na:na]
	at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1228) ~[na:na]
	at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(ServiceLoader.java:1273) ~[na:na]

madukan avatar Jul 09 '24 21:07 madukan

Hrm. Ok, I'll release 0.9.4 now, see how you get on with that. It should be on Maven central in the next hour.

brett-smith avatar Jul 09 '24 21:07 brett-smith

0.9.4 works! Nice work!

Following error is printed in the console, however I get the notification on MacOS 14.5 without other issues.

ScriptEngineManager providers.next(): javax.script.ScriptEngineFactory: Provider apple.applescript.AppleScriptEngineFactory not found
ScriptEngineManager providers.next(): javax.script.ScriptEngineFactory: Provider apple.applescript.AppleScriptEngineFactory not found

Output/Notification: image

Dependancy:

        <dependency>
            <groupId>com.sshtools</groupId>
            <artifactId>two-slices-swt</artifactId>
            <version>0.9.4</version>
        </dependency>

Code:

import com.sshtools.twoslices.Toast;
import com.sshtools.twoslices.ToastType;

Toast.toast(ToastType.INFO, "Information", "Here is some information you cannot do without.");

madukan avatar Jul 09 '24 22:07 madukan

Great, thanks for reporting back. 0.9.4 contained a "fix" for that error message, but of course it won't work if you are actually on a Mac. The problem is it's trying to look for Growl support, when really with modern Java + Mac OS it's never going to find it.

I think I'll probably just drop the scripted Growl support.

FYI, the screenshot you have posted looks like it is NotificationCenterToaster or OsXToaster, so you will not need that SWT module. That suggestion was only a (failed) work around for the bug in 0.9.3 anyway.

In the meantime, setting a specific toaster yourself when on Mac should stop the error.

ToasterSettings settings = new ToasterSettings();

// Pick one of ...
//   com.sshtools.twoslices.impl.OsXToaster (works out of box - probably the one your are using)
//   com.sshtools.twoslices.impl.NotificationCenterToaster (requires JNA on classpath, special permissions)
//   com.sshtools.twoslices.swt.SWTToaster (requires SWT two-slices module and SWT itself on classpath)
//   com.sshtools.twoslices.impl.JavaFXToaster (requires JavaFX on classpath)
//  com.sshtools.twoslices.impl.AWTToaster (works out of box, if java.desktop is available)
if(System.getProperty("os.name").toLowerCase().contains("mac os")) {
    settings.setPreferredToasterClassName("com.sshtools.twoslices.impl.OsXToaster");
}

ToasterFactory.setSettings(settings);

brett-smith avatar Jul 10 '24 00:07 brett-smith