OSGi Karaf Scala UnsupportedAudioFileException - scala

this is my first post here. I'm currently working on a simple http audio servlet in Scala on Apache-Karaf 3.0.0. I'm deploying it as a feature from inside some bundles, which I've built using a maven project. I'm using the 'javax.sound.sampled' library to get the audio, and I'm loading the file from the AudioSystem with 'java.io.File'.
val file = new File("audioFile.wav")
val audioStream = AudioSystem.getAudioInputStream(file)
This is obviously not the actual code, as I've stripped out all of the trivial bits. But this is where it fails, on the 'getAudioInputStream' call.
When I deploy this code to Karaf it fails with 'UnsupportedAudioFileException'. The file does exist, and is readable, I've already validated this. Also, I've made sure that this code can be run under the following.
- Scala 2.10.2, 2.10.3
- Java 1.7.0_45 ( This is the same JRE as my Karaf program is using )
- SBT 0.12.4 ( With the different Scala versions )
The only place this fails is when I deploy it to Karaf. I don't know if Karaf has cut out some random audio support, or what is going on, because this otherwise works when deployed through SBT or using the Scala command line. I've also looked into alternative libraries, but to no avail. Most other solutions seem to be based around actually playing the audio through a sound driver, which is useless to me. I need the actual byte data.
Also, keep in mind that just sending the file over is also useless me. Another requirement is that I need to be able to be able to merge multiple audio files in to one seamless audio stream. I already have this done, I just need to port it to OSGi, and for some reason I am now getting this error. I don't know if Karaf has something to do with it, or if my building it through a Maven project has broken something. I've looked around, and have found very little hint as to where the problem might be.
The audio files I'm using are of Waveform audio. 8,000 sampling rate, 16 bits per sample. I don't think this would actually make a difference, but I'm no expert on audio formats.
My pom.xml dependencies are as follows. The only plugin I'm using is the Scala compiler, and of course my root pom.xml is using the org.apache.felix maven-bundle-plugin. There's really not much magic going on here, yet the mystery remains.
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>2.10.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
Any clues would be greatly appreciated, thank you.

I think AudioSystem is not fully OSGi ready. This is what I found in the Aries Spy Fly dcoumentation.
Not sure what exactly you have to do to make it work but this might help.
https://aries.apache.org/modules/spi-fly.html
Special Cases
SPI Fly can be used for most SPI provider/lookup systems that use the TCCL pattern to obtain implementations. However in some cases, some special treatment is needed. This special treatment is often needed when the API itself does not match the name of the resources in META-INF/services, java.util.ServiceLoader is such a case, however SPI-Fly has built-in knowledge of ServiceLoader. Known APIs that require special treatment are listed below:
javax.sound.sampled.AudioSystem: This class uses sun.misc.Service under the covers (via com.sun.media.sound.JDK13Services) which is a predecessor to java.util.ServiceLoader. There is no special treatment for sun.misc.Service in SPI Fly (yet), but the AudioSystem.getAudioInputStream() API can be made to work by explicitly listing it in the provider bundle (the one that contains the relevant META-INF/services resources): SPI-Provider: javax.sound.sampled.AudioSystem on the consumer side you can use SPI-Consumer: javax.sound.sampled.AudioSystem#getAudioInputStream

Christian's answer is correct but I wanted to provide an updated link to the spifly documentation page. Specifically:
Java's java.util.ServiceLoader.load(), other similar methods such as
sun.misc.Service.providers() and also other static finder methods such
as the FactoryFinder.find() methods try to locate 'service'
implementations by looking for resources in the META-INF/services
directory of all the jars visible to the Thread Context ClassLoader
(TCCL).
There are a number of issues with the above mechanisms when used in
OSGi:
The Thread Context ClassLoader is not defined in general in an OSGi context. It can and has to be set by the caller and OSGi cannot
generally enforce that.
A bundle can't Import-Package META-INF/services as potentially many bundles will contain this pseudo-package and the OSGi framework
will only bind a single exporter to an importer for a given package.
Instantiating an SPI provider generally requires access to internal implementation classes, by exporting these classes an
implementing bundle would break its encapsulation.
Even if an implementation class was exported, importing this class in a consumer bundle would bind it to the specific implementation
package provided, which violates the principle of loose coupling.
Bundles have a dynamic life-cycle which means that provided services could disappear when a bundle is updated or uninstalled. The
java.util.ServiceLoader API does not provide a mechanism to inform
service consumers of such an event.
The SPI Fly project makes it possible to use existing code that uses
ServiceLoader.load() and similar mechanisms under OSGi.
Please note that as of 2016-05-20 new versions of the com.googlecode.soundlibs artifacts were uploaded to the maven central repository. These new versions of the artifacts are proper OSGi bundles. This will help everyone who needs to use the Java Sound API within an OSGi container
I created a simple example project on github that demonstrates how to play an MP3 file inside an OSGi container using the Java Sound API. Checkout the branch static-weaving and dynamic-weaving to see the respective solutions.

Related

How do you use play framework as a library, in a scala project

Use Play Framework as a component got a server up, but configuring the file system paths for routes file, views, etc, give or take having to take care of a thread pool for the embedded play server is a different story. Basing on the aforementioned, I started a template for including play as a library, but it remains unclear how to wire the paths, hopefully in an IDE-import friendly way too, so that Play can be nicely used in an existing non-play project, as a library.
How do you configure the file system paths for the routes file and views?
What else should be handled for being as robust as running as the framework?
Anything special for bundling the project for deploy with Play now included?
Motivation: Adding Play to a project, in the current state of affairs, means wrapping the project definition and structure around Play, and losing full compilation in sbt (because only run completes the compilation when using the play sbt plugin). As future Spray support is vague and Akka http is beta-ish, using Play as a library seems to plug a hole.
Somehow this didn't pop up in google, until someone suggested the link on gitter: https://www.playframework.com/documentation/2.5.x/ScalaEmbeddingPlay
Note that an application.conf file containing the required crypto secret can simply sit under src/main/resources in this embedded mode (up until you want to override it for production as per the documentation about it). This is quite enough for a REST server.
However now back to the docs, in case you want more than REST:
This can be used in conjunction with the Twirl template compiler and Play routes compiler
So for Play view templates (which are twirl templates really), refer to the repo I mention in the question body, in which #JonasAnso kindly enabled exactly that.

Scala class file broken error over Java jar

I have run into a compilation error:
[warn] Class com.google.api.client.auth.oauth2.Credential not found - continuing with a stub.
[error] error while loading GoogleService, class file '....../gdata-core-1.0.jar(com/google/gdata/client/GoogleService.class)' is broken
I found this similar question but couldn't successfully use its solution for my case. How can I trace what's actually broken in this jar as per the Scala compiler (i.e. get the details of what's actually broken), to make sure what the solution aught to be?
The source where I think this Google jar builds from, is here.
Note: unlike the other questions, in my case, the google jars are included unmanaged in my project, in the lib directory, as per these google setup instructions.
As described in your linked answer, this error happens when a class contains some annotations which are no longer present on the classpath. Java considers this acceptable, but Scala does not. You'll generally only run into this problem with heavily optimized java libraries where they've deliberately excluded the "unnecessary" annotations. Google does this for a lot of their code; to be perfectly honest I don't think I've ever seen the problem in any non-google libraries.
The pragmatic solution is to use advanced search on maven central to find the jar that contains the missing class. If gdata-core had been built with maven (as most serious java libraries are these days), it would be easy to see from the <dependencies> section of pom.xml which dependencies had been declared optional, and therefore figure out where any classpath problems of this kind were likely to be. Unfortunately this particular library is still built with ant, so it's hard to determine the build classpath without reading the whole build.xml and figuring it out "by hand".
Had to find a google supplied jar file where the class mentioned in the warning (class Credential) is contained, and stick it in my lib directory used by sbt.
With really a lot of heuristic, it turned out to be the jar file google-oauth-client-1.18.0-rc.jar which I obtained here and equally exists here, after figuring that the source file that the error is for, simply does not define that class itself but rather imports it from a different package com.google.api.client.auth.oauth2. I guess the latter package must have been present at compile time, and its compiled class is necessary for Scala being able to use the classes contained in the former jar, at least when Scala is involved.
Not exactly sure how the build system at google produced all of this, and how to pin down the annotations that made the additional jar required for Scala, but the missing class is no longer missing for Scala.
Hope someone would chime in to provide a deeper answer, as to how to pin down the details of a class being broken for scala, and how to trace back where to obtain it sans my heuristic search.

Architecture for plugins to be loaded in runtime

Considering that I am developing an end-user software program (as an uberjar) I am wondering what my options are to make it possible for the user to download a plugin and load that during runtime.
The plugin(s) should come compiled and without source code, so sth. like load is not an option.
What existing libraries (or ways of Java...?) exist to build this on?
EDIT: If you are not sure I would also be satisfied with a way that costs a reboot/-start of the main-program. However, what is important is that the source-code won't be included in any JAR file (neither main application nor plugin-jars, see :omit-source of Leiningen documentation).
To add a jar during runtime, use pomegranate which lets you add a .jar file to the classpath. Plugins of your software should be regular Clojure libs that follow certain conventions that you need to establish:
Make them provide (e. g. in an edn) a symbol to an object implementing a constructor/destructor mechanism such as the Lifecycle protocol in Stuart Sierras component library. In runtime, require and resolve that symbol, start the resulting object and hand it over to rest your programs plugin coordination facilities.
Provide a public API in your program that allows the plugins to interact with it in ways that you coordinate asynchronously e. g. with clojure.core.async (don't let one plugin block the entire program).
Make sure that the plugins have a coordinated way to expose their functionality to each other only if they desire so to enable a high degree of modularity among your plugins. Make sure that your plugin loader is capable of detecting dependencies among plugins and is capable of loading and unloading them in the right order.
I've not tried it myself, but you should in theory be able to get OSGi to work with Clojure.
There's a Clojure / OSGi integration library here:
https://github.com/aav/clojure.osgi
If I were to attempt to role my own solution, I would try using tools.namespace to load and unload plugins. I'm not entirely sure it will work, but it's certainly in the right direction. I think one key piece is that the plugin jars will have to be "installed" in a location that's already on the classpath.
Again, this is only the start of one possible solution. I haven't tried doing this.

What is the best way to create a new Play! 2.1 module?

As of Play 2.0, it appears that there is no longer a way of creating a module for an existing Play application, other than by creating a new Play application. Having searched around a bit, I came across these instructions, which indicate that I must (or at least should) delete any routes created in the new module (application), and that the module's application.conf file is really just a stub that is required in order for the module to be recognized as a Play application.
I am new to Play, but apparently there used to be a console command ('new-module') for generating a module, which presumably created only those files which were needed for the module to be discovered by the application. It seems to me like it would still be useful to be able to quickly create a new module in this way, especially if registering a new module from the console also added the module to your build, and to the repository of your choice, thus removing the requirement for (as much) manual wiring.
I would also like to be able to maintain Play modules upon which my application depends as part of the same codebase/build, such that, when I make changes to a module, they are picked up at application compile time (for example, when play is ~ running and and a changed file is saved). Does this already happen with modules registered as dependencies, or must I rebuild modules independently of my application?
Because I am a newcomer, I'm not positive that there isn't a way to do accomplish these tasks in an automated manner. There is a chapter on packages and modules listed in the Play for Scala book (Part III, chapter 9), but the book is not yet complete and that chapter is, unfortunately, yet unwritten.
If an experienced Play! developer would be so kind as to either confirm that the instructions to which I linked above are still the recommended procedure for creating a module and registering/maintaining it as a dependency, or else list a better procedure, I would greatly appreciate it.
Most of the information is valid.
To Play 2.x there is no difference between a regular library and a Play module (a library which itself depends on the play library jar).
The part about the routes file is still valid, but they introduced 'Sub-Router composition' to give you some extra freedom (search for 'Allow more modularization for your projects' on the highlight page).
Libraries (and thus Play modules) are referenced in the Build.scala file with version, for example:
"play.modules.mailer" %% "play-mailer" % "1.1.0"
If you are developing a module yourself you could use the 'publish-local' command to make sure other projects on your computer can find the dependency. Because modules are essentially versioned libraries you need to compile them separately from your application. However no-one is preventing you from running scripts to automate things.

How to add jars properly to a eclipse bundle

I got a little problem. I want to use hibernate in an eclipse rcp. (i'm new to osgi and eclipse rcp). So I added the jar into the plugin-project folder and the build path and the bundle build path, but when I try to use hibernate from my bundle, it crashes with a ClassNotFoundException.
What is the proper way to do this?
Pls look at eclipse buddy policy. This might help you if you are facing class not getting loaded because of osgi classloading.
Hibernate, and many other classic Java programs (ab)use dynamic class loading to to connect the different parts. They classes they use are read from a file and then loaded with Class.forName. This is fundamentally not-modular since these classes are by definition implementation classes, which should be hidden.
Since OSGi is a modularity framework it puts fences around a module (a bundle) and refuses to load anything that is not properly exported and imported. So if Hibernate does its Class.forName it will run right into this fence, as it should be to get the advantages of modularity.
Eclipse Buddy policy is like a huge hole in this fence, moving things back tot he bad old classpath: linear search. With a buddy policy, Eclipse will just start searching if there is a class somewhere that has that name. Since this ignores versions, you can no longer rely on proper version handling. The good news is that it works most of the time. The bad news is that you loose privacy and when it does not work you get weird errors.
With Hibernate, only solution is to not use the text file setup but use the API and give Hibernate the actual classes. In those cases Hibernate will use the class loader of those classes and that works. In OSGi, as long as you follow the Java language rules there are no problems.
To handle the kind of problems that class loading hacks address OSGi uses services.