Closed edvin closed 8 years ago
I realise that many will also want to use Declarative Services for other things in ther apps, and they might not want to use an Activator just to expose some Views. I'm adding a sample to the IntelliJ IDEA Plugin that shows how you would expose the View using declarative services instead. It will look something like this:
class PieChartView : View() {
override val root = piechart("Imported Fruits") {
data("Grapefruit", 12.0)
data("Oranges", 25.0)
data("Plums", 10.0)
data("Pears", 22.0)
data("Apples", 30.0)
}
@Component class Registration : ViewProvider {
override val discriminator = "dashboard"
override fun getView() = find(ChartView::class)
}
}
Here I'm implementing the ViewProvider
interface and adding the @Component
annotation. I've also update the dependencies and build config in the deployment descriptor for this bundle.
Does this look OK?
Was this initiative abandoned?
No, everything is implemented and working, and I got some replies on Twitter, but nothing here :)
Dear All, I was going through the OSGi integration offered by TornadoFX. I got the sample application up and running on karaf by creating a feature for all the required bundles rather than manually copying them to the deploy folder as is the case with felix.
The feature file looks as follows:
`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
Nice work on the feature file :)
You should be able to stop bundles that provide applications via the context.registerApplication
hook, but there is a limitation in that you cannot stop the actual TornadoFX bundle.
The TornadoFX bundle already configures Platform.setImplicitExit(false)
. If you set it to true
in your app then I suspect the the Platform exits and you're unable to start another application after that.
I'm not quite sure I understand what you want to do. Do you want to keep the bundle running, but unregister the app when the last window closes, is that it?
Thanks for the quick response. I have not yet looked at the implementation of context.registerApplication / context.unregisterApplication extension functions.
I will give a little background on how to develop & deploy our javafx apps.
The app and its dependencies are deployed as shown below:
app.jar | lib | a.jar | b.jar
The lib/a.jar;lib/b.jar classpath entries are captured in the app.jar's manifest.mf. We launch the application via the normal java -jar app.jar. A shortcut is created and placed on the desktop of the user for him to launch the app whenever required.
When the main stage is closed we do not close the app, but we put it in the system tray with options to show & close. On click the show, the stage is brought back and shown to the user. On click of close button, we close the app itself.
I am not sure if the same behavior of customer initiating a start / stop of the application is feasible in osgi parlance. Start typically happens when the bundle is activated and stop when the bundle is stopped or osgi framework is shutdown. If the user has closed the stage by mistake, he has to restart the osgi framework or manually stop the bundle (providing the application) and start that bundle again.
Is there a possibility of exposing the context.registerApplication / context.unregisterApplication via jmx or something so that we can invoke to same from outside the framework ?
best regards Sriraman.
Ah, yes that could be possible. Let me have a look early next week and get back to you :)
Just so I know I understand your requirement correctly.. If the user closes the window, you close the stage, and the app still runs.
In this case, are you able to show your app again, or aren't you?
Since the app is still running, you should be able to call FX.primaryStage.show() and be back in business.
In your case when the user actively closes the application, you want to shut down the bundle or shut down the whole OSGi environment?
Edvin,
To reproduce my behavior, you can do the following:
We do not show the osgi console to the end users. It is only for development purposes. Mostly, osgi runtime itself runs as a system service. (we use karaf)
There is no external control in terms of the starting the app. The app starts when the bundle gets activated. Are there any other ways of starting / stopping the app without getting into the osgi shell.?
Hope this answers your question.
Also, as you mentioned, from where do I make the call to FX.primaryStage.show() ?
Wouldn't this be the exact same problem without OSGi? Without an UI, how would you reopen the app window for the user? Could you install a tray icon to allow the user to reopen the app window through a tray icon action? If not, where do you envision the user interaction that should reopen the window to accur?
Hey,
In a non-osgi environment, we currently do the following. On close of stage by clicking on the close button the stage.setOnCloseRequest is fired and we hide the stage. However, we have a system tray icon with a popup menu having two more options (show /close). If show is selected, we show the stage again. and if close is selected we end the jvm via System.exit(0). The app is launched via java -jar app.jar. Hence, after the close, if the user wants to relaunch the app, he / she can do so by clicking on the desktop short cut again which launches the jvm and launches the main class which is a javafx application class.
I am just wondering if something like this can be reproduced on an osgi environment.
Ah, I see. So the tray icon close action stops the bundle, and then you want to relaunch that bundle by starting another process, but keep the same JVM.
I can see a number of ways to solve that. One would be to launch your OSGi environment via a custom main method and use JUnique to detect if you should start the OSGi environment or simply send a signal to the running JVM so it can restart the bundle.
Would that solve it, or is it too clunky? I have some other ideas as well, but this should be fairly easy to configure at least.
Also, you do want to keep the OSGi container running after the UI exits, right? But you didn't do this prior to introducing OSGi, right?
We have not ported our app on an osgi environment yet. What we intend to do as part of the osgi port is to achieve the following:
Does these steps look okay. ?
Yes, this looks OK and is most probably not too hard to achieve. You are right about that you need a launcher in front of the OSGi environment.
This is far easier to achieve if you actually make that launcher so that it starts the OSGi environment embedded. Then it could start it if it receives an initial request, or just start the right bundle to get the UI back up etc. As I mentioned, JUnique is a library that makes this very simple. If you don't want to depend on a third party lib, it should be fairly easy to write this yourself.
Alternatively, have one bundle listen on a port and send signals to that so it can start/stop the right bundles.
The TornadoFX bundle will keep the JavaFX Platform running so that you can register and unregister TornadoFX apps at will. The rest is just plumbing around these concepts.
I don't think any special support in TornadoFX will make this easier, lest you have something specific in mind. However, if you need help with sorting out how to do this, I'd be happy to help, but I would need a couple of days before I have time. Need to finish some documentation for TornadoFX first, and kick off the shiny new KDBC framework :)
I would start with embedding Felix, as that is quite straight forward and well documented. What do you think?
Thanks for your time and suggestions. As such I am new to both Kotlin and tornadofx. I will also go through the tornadofx documentation and see how to achieve what was described earlier. Will trouble you as and when I am stuck. Hope you don't mind. :)
Great, please ask if anything is unclear or missing from the guide, or if you get stuck in any way. We'll help for sure :)
As demonstrated in the OSGi screencast, TornadoFX let's a bundle export a View to other bundles by calling this function:
Under the covers, this implements an interface called
ViewProvider
and callsBundleContext#registerService
with that implementation.Here is the actual
registerView
function:TornadoFX hides the need to implement this interface, but doesn't force you to abandon DS - you might just as well implement the interface manually. The choice is entirely up to the user, but you actually write less code by using the
registerView
extension function, and you don't need the extra build step so I suspect TornadoFX users will prefer the explicit way demonstrated in the screencast.Granted, I'm no OSGi expert, and any input is greatly appreciated.