How is SPI (Service Provider Interface) works?

J

jacksuyu

Can I define my own SPI?

I read some document, seems need to put service class under
META-INF/services directory

like
filename: com.my.SPIInterface

content: com.my.myimplemeentationclass

But seems that doesn't work...

Any formal documents?

Thanks.
 
T

Thomas Fritsch

Can I define my own SPI?

I read some document, seems need to put service class under
META-INF/services directory

like
filename: com.my.SPIInterface

content: com.my.myimplemeentationclass

But seems that doesn't work...

Any formal documents?

Thanks.
There is a description (well-hidden) in the API doc:
<http://java.sun.com/j2se/1.4.2/docs/api/javax/imageio/spi/ServiceRegistry.html>.
Don't be irritated by the fact that this class is part of ImageIO. It is
applicable generally, not only for ImageIO.

See also
<http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service Provider>.
But that description is somewhat lousy, because the code-example given there
uses an undocumented class (sun.misc.Service). You can safely use a
documented class (javax.imageio.spi.ServiceRegistry, see above) instead.
 
J

jacksuyu

It appears different service take SPI values in different way....

I tried to write dummy SPI, and load from META-INF/services directory,
works fine.
but for this sample:
http://www.javaworld.com/javaworld/jw-11-2000/jw-1103-mp3.html

I tried the following code to call mp3.jar
import java.io.*;
import javax.sound.sampled.*;

public class A {

public static void main(String[] args) {
String fName = "a.mp3";

new A(fName);
}

public A(String sound) {
try {

AudioInputStream stream = AudioSystem.getAudioInputStream(new
File(sound));

// At present, ALAW and ULAW encodings must be converted
// to PCM_SIGNED before it can be played
AudioFormat format = stream.getFormat();

if (format.getEncoding() != AudioFormat.Encoding.PCM_SIGNED) {
format = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED,
format.getSampleRate(),
format.getSampleSizeInBits()*2,
format.getChannels(),
format.getFrameSize()*2,
format.getFrameRate(),
true); // big endian
stream = AudioSystem.getAudioInputStream(format, stream);
System.out.println("\nConverted stream:");
printFormat(format);
}

DataLine.Info info = new DataLine.Info(Clip.class,
stream.getFormat());
Clip clip = (Clip) AudioSystem.getLine(info);

// Add a listener for line events
clip.addLineListener(new LineListener() {
public void update(LineEvent evt) {
if (evt.getType() == LineEvent.Type.STOP) {
System.out.println("Sound stopped.");
System.exit(0);
}
}
});

System.out.println("Playing sound...");
clip.open(stream);
clip.start();
} catch (IOException e) {
e.printStackTrace();
} catch (LineUnavailableException e) {
e.printStackTrace();
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
}
}
}

I always get javax.sound.sampled.UnsupportedAudioFileException: could
not get audio input stream from input file

error. And the class specified in META-INF/services directory never
work.....


I checked com.sun.media.sound.JDK13Services.getProviders method
it appears need priviledge to return values, but I don't know which
priviledge and permission to run that process. And JDK13Services catch
throwable without print any message!!!!!

Any more suggestion?

Thanks.
 
T

Thomas Fritsch

It appears different service take SPI values in different way....
I have absolutely no experience with Java audio. But nevertheless it
would surprise me, if Sun deviated from its canonical way of loading
SPIs here.
I tried to write dummy SPI, and load from META-INF/services directory,
works fine.
but for this sample:
http://www.javaworld.com/javaworld/jw-11-2000/jw-1103-mp3.html

I tried the following code to call mp3.jar [...code snipped...]

I always get javax.sound.sampled.UnsupportedAudioFileException: could
not get audio input stream from input file

error. And the class specified in META-INF/services directory never
work.....


I checked com.sun.media.sound.JDK13Services.getProviders method
it appears need priviledge to return values, but I don't know which
priviledge and permission to run that process. And JDK13Services catch
throwable without print any message!!!!!

Any more suggestion?
In your situation I would check several things:
(1) Does your Java really see the jar file?
You can verify this by
System.out.println(System.getProperty("java.class.path"));
somewhere in your application code.
A safe and simple way to achieve this is to put the jar file
into the ".../jre/lib/ext/" directory of your JRE. And of course,
if you have more than 1 JREs on your system (for example:
"C:\Programme\jdk1.5.0_04\jre\" and "C:\Programme\jre1.5.0_04\"),
be sure to put into the correct JRE.
(2) Is your service provider class really loaded?
You can check this by calling your application with
java -verbose:class ...
And if encountering problems with a self-written SPI class:
(3) Is your class public? Has it a public no-arguments constructor?
(4) Does the SPI framework really load and instantiate your class?
To verify this you can insert some System.out.println(...) lines
into the class-initializer static {....}
and into the no-arguments constructor.
 
J

jacksuyu

Thanks for the suggestion.

After put in java -verbose:class... , I figured out the problem was
because that mp3.jar is not compatible with my mp3 files. Seems it is
just too old.

Nevertheless, the SPI loading works great.

Thank you.!!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,433
Messages
2,571,683
Members
48,796
Latest member
Greg L.

Latest Threads

Top