Fragmentation of JSRs is a problematic issue
in Java ME, in general: your application requires a certain JSR for its
functionality, yet that JSR is not supported on the target device.
There are no magic solutions that you can apply, even when it comes to
Symbian OS. If a JSR is not supported on a certain device, there is not
much you can do about it. However, Java ME on Symbian OS gives phone
manufacturers a large common set of JSRs, on the scale of the set of MSA
1.1 Component JSRs. That reduces the amount of JSR fragmentation
considerably for Java ME applications targeting Symbian smartphones.
There is a difference between the Java ME platform
being formally compliant with MSA and the Java ME platform supporting
the set of MSA 1.1 JSRs. A Java ME platform that supports all MSA
Component JSRs but does not comply with all MSA clarification is still
not MSA-compliant. Without playing down the lack of compliance, the
major importance for a developer is probably the availability of JSRs.
Unlike many low-end platforms, which support only MIDP 2.0 or JTWI, the
latest Symbian smartphones are already compliant with MSA Subset and
support additional Component JSRs that bring them closer to MSA Fullset.
In reality, JSR fragmentation will always exist to some extent.
We discuss two guidelines on how to handle JSR
fragmentation according to the modularity of your application. In the
graceful functional degradation approach, your application can execute
without the unsupported JSR, although with degraded functionality. In
the optionally replaceable module approach, your application can remain
at the same functional level by using another JSR, which is supported.
1. Graceful Functional Degradation
All references and usage of a JSR that may not be
supported need to be encapsulated within a bounded part of the
application. If the JSR is not supported by a specific device, that part
of the application is never accessed in any way. It is not instantiated
or used and there must be no direct usage of the JSR outside this
module.
To encapsulate all usage of that JSR, you also need
to define interfaces between that module and the rest of the application
that are the only way of accessing the JSR (see Figure 1). The module is loaded and used only after detection to check for the JSR availability.
For example, your application should encapsulate all
usage of JSR-82 in a module, behind a set of interfaces that are used to
send and receive messages over Bluetooth. When your application starts,
it detects if Bluetooth is supported and instantiates the Bluetooth
module, or not. The usability of the application must also be changed
and any functionality dependent on Bluetooth should be disabled (e.g.,
commands or menu items that trigger usage of Bluetooth should be
disabled or removed).
private void initBluetoothFunctionality(){
try {
Class c = Class.forName("javax.bluetooth.LocalDevice");
// if we reach here, JSR-82 is supported
btModule = new MyBluetoothCommModule();
// TODO: enable all Bluetooth-related functionality
}
catch (ClassNotFoundException e) {
// JSR-82 is not supported on this handset
btModule = null;
// TODO: disable all Bluetooth-related functionality
}
}
The advantage to this approach is that the module can
always reside in the JAR. There is no need to maintain multiple
versions with and without the module. If the JSR is not supported, the
module is not used. The disadvantage is that the JAR is sometimes
needlessly bigger than it could have been.
2. Optionally Replaceable Module
The optionally replaceable module approach implies
that your JAR includes more than a single implementation of the required
module (see Figure 2).
The solution design is similar to the previous case but there is a
fallback mechanism and the run-time module can be replaced by more than
one implementation, so more than one module implementation would reside
in the JAR.
A possible usage of this solution is to implement the
model–view–controller (MVC) design pattern with more than one view
module. In the JAR, there would be two or more implementations of the
application view, each using a different JSR. For example, one
implementation may use JSR-226 SVG, another implementation may use
JSR-184 3D Graphics, and a third implementation may use Canvas:
private void loadUiModule() {
// first attempt - JSR-226 SVG
try {
Class c = Class.forName("javax.microedition.m2g.SVGAnimator");
// TODO: load SVG implementation of UI
ui = new UiModuleSVG();
}
catch (ClassNotFoundException e) {
// JSR-226 SVG is not supported
}
// fallback option 1 - JSR-184 3D
if (ui == null) {
try {
Class c = Class.forName("javax.microedition.m3g.Graphics3D");
// TODO: load 3D implementation of UI
ui = new UiModule3D();
}
catch (ClassNotFoundException e) {
// JSR-184 3D is not supported (unlikely in Symbian OS!)
}
}
// last fallback option - MIDP LCDUI
if (ui == null) {
ui = new UiModuleLCD();
}
}
The advantages and disadvantages are the
same as with graceful functional degradation – the module is always in
the JAR, which means the JAR is bigger but there is only one JAR to
maintain.