Signal Framework is a Spring-based IoC framework for the Java ME (J2ME) platform. The framework has been built to overcome the limitations of the CLDC API that prevent IoC containers implemented in Java SE from running on J2ME. Signal uses regular Spring XML configuration files, allowing developers to leverage existing tools and skill sets while coping with the limitations of J2ME.
The reflection support in the CLDC API is very limited compared to Java SE. The API only allows objects to be constructed with default (no-arg) constructors. It is not possible to pass arguments to constructors, invoke methods, access fields or create dynamic proxies.
To overcome those limitations the framework reads context configuration files when an application is compiled and generates Java code responsible for instantiating a context at runtime. When a J2ME application is started, it executes the generated code instead of loading any configuration files. In effect an application context is created at runtime without relying on XML parsing or advanced reflection features. The footprint of the generated code is very small, because the IoC runtime only consists of several classes.
An alpha release that this documentation pertains to only includes an early version of the IoC container and associated build tools. This release will be followed by a beta in June that should include a polished IoC container and a simple MVC framework built on top of MIDP 2.0. Further plans will depend on the feedback received from the first users.
Signal Framework supports the following features of the Spring IoC container.
Spring XML-based configuration files
Dependency injection through contructor arguments and properties
Autowiring
The following notable features are not supported in the alpha release:
Lazy initialization
BeanFactoryAware
AOP
Bean post-processors
Pre-processing of a context is handled by a Maven plugin. Note that the plugin is just a thin wrapper for a context generator (signal.tools.context.jar) so it should be easy to add support for other tools (e.g. Ant) in the future.
The plugin (net.sourceforge.signal:maven-signal-plugin) can be downloaded from the following repository: http://signal.sourceforge.net/m2repo/
The following example shows how to add the Signal repository to a pom.xml file:
<pluginRepositories> <pluginRepository> <id>signal-plugin-repo</id> <url>http://signal.sourceforge.net/m2repo/</url> <snapshots> <enabled>true</enabled> </snapshots> <releases> <enabled>true</enabled> </releases> </pluginRepository> </pluginRepositories>
Two mandatory plugin parameters need to be specified:
contextFile - a file to read context configuration from
targetClassName - a fully qualified name of a context class to be generated
In addition to that an optional outputDirectory can be specified. By default the generated classes are placed in ${project.build.directory}/generated-sources/signal.
The plugin needs to be executed during the process-classes phase so that other classes that might be referenced in a context configuration file are already compiled. This implies that an additional invocation of maven-compiler-plugin is needed to compile the Java code generated by the Signal plugin.
The following example taken from signal.examples.context shows how to properly set up the plugin (note that the order of plugins is important):
<plugin>
<groupId>net.sourceforge.signal</groupId>
<artifactId>maven-signal-plugin</artifactId>
<version>0.1-alpha</version>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>generate-spring-context</goal>
</goals>
<configuration>
<contextFile>src/main/resources/net/sourceforge/signal/examples/context/core/greeter.xml</contextFile>
<targetClassName>net.sourceforge.signal.examples.context.core.GreeterContext</targetClassName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>target/generated-sources/signal</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<source>1.3</source>
<target>1.3</target>
<compilerArguments>
<bootclasspath>
${settings.localRepository}/org/microemu/cldcapi11/${microemulator.version}/cldcapi11-${microemulator.version}.jar${path.separator}${settings.localRepository}/org/microemu/midpapi20/${microemulator.version}/midpapi20-${microemulator.version}.jar
</bootclasspath>
</compilerArguments>
</configuration>
</execution>
<execution>
<id>context-compile</id>
<phase>process-classes</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<source>1.3</source>
<target>1.3</target>
</configuration>
</execution>
</executions>
</plugin>
There are two ways to load a generated context class at runtime:
The net.sourceforge.signal.runtime.core.context.ContextClassLoader class can be used directly, for example:
IContext ctx = ContextClassLoader.getInstance().loadContext("some.package.SomeContext");
Alternatively, the context can be loaded by subclassing net.sourceforge.signal.runtime.ui.mvc.ApplicationMIDlet, for example:
public class ContextMIDlet extends ApplicationMIDlet
{
public ContextMIDlet() throws Exception
{
super("some.package.SomeContext");
IContext ctx = super.getContext();
}
}
Once a reference to an context object is established the net.sourceforge.signal.runtime.core.context.IContext.getBean method can be used to retrieve beans.
For more information refer to the Context API Javadoc and the signal.examples.context subproject in the source distribution.