Author: Timo Laitinen
Date: 2006-04-16
1. What is JICE?
- JICE = Java Instance Configuration Engine
- JICE is an XML-based Inversion of Control (IoC) Container - tool for initializing and configuring Java applications.
- JICE is essentially an XML-to-Java mapping tool
-
JICE consists of:
- JIC Language - An XML vocabulary for describing graphs of Java objects.
- JIC Engine - a Java application that constructs graphs of Java instances based on the XML data.
- JICE could be used in any kind of Java application (server, client, applet, etc.)
JICE is used for defining objects in a Java application. Instead of writing Java code that creates the application objects, the objects are described in XML files that are transformed to running objects with JICE. This way the dependencies between the Java objects are easier to manage.
As an IoC container, the strengths of JICE are:
-
Support for POJOs (Plain Old Java Objects):
- objects may have any kind of method signatures - JICE is not restricted to bean-like setters and getters.
- objects may use number of constructor arguments.
- support for primitives.
- support for arrays (and for the Collections API).
- both instance and static methods may be called.
- nice XML format - the format is compact and descriptive, without meta-level elements such as "object" or "property".
The sections Using JICE for Constructing Applications and Using JICE for Configuring Applications explain the advantages of using JICE.
2. A Simple Example
Lets assume that we have an application that uses java.text.DateFormat
for formatting dates. Instead of hardcoding the format into the Java code or putting it into properties files, we use JICE for defining the java.text.DateFormat
instance.
2.1. Write a JIC File
First, we would write the following kind of JIC file:
<dateFormat xmlns="http://www.jicengine.org/jic/2.1" class="java.text.SimpleDateFormat" args="pattern,locale">
<pattern>dd.MM.yyyy HH:mm:ss z</pattern>
<locale class="java.util.Locale" args="language,country">
<language>fi</language>
<country>FI</country>
</locale>
</dateFormat>
The file defines a java.text.SimpmleDateFormat
instance with the pattern dd.MM.yyyy HH:mm:ss z
and locale fi,FI
. It corresponds to the following Java code:
java.text.DateFormat dateFormat; String pattern = "dd.MM.yyyy HH:mm:ss z"; String language = "fi"; String country = "FI"; java.util.Locale locale = new java.util.Locale(language,country); dateFormat = new java.text.SimpleDateFormat(pattern,locale); return dateFormat;
2.2. Process the JIC File
In the application, the DateFormat
instance would be obtained by processing the JIC file with the following Java code:
try { // locate the jic file org.jicengine.io.Resource jicFile = new org.jicengine.io.FileResource(new java.io.File("examples/DateFormat-2.jic")); // process the file with JIC Engine Object result = org.jicengine.JICEngine.build(jicFile); // we assume that we got a DateFormat instance java.text.DateFormat dateFormat = (java.text.DateFormat) result; // use the dateFormat for something.. } catch(Exception e){ // handle the exception.. }
The code invokes JIC Engine that actually processes the file. JIC Engine reads the XML data and uses reflection for creating the required Java instances.
2.3. Consequences
- The pattern and locale may now be changed by editing the JIC file - no recompilation is needed.
-
Details are hidden from the application - the application does not know how the
DateFormat
was created. It knows only that a specific JIC file will yield aDateFormat
instance. -
If we would like to define multiple date formats for different situations, we could either:
- Write many JIC files that define different kind of date formats and choose the appropriate file at runtime by some criteria.
- Alter the JIC file so that it obtains the
DateFormat
from a factory.- For example,
java.text.DateFormat.getDateInstance
could be called from the JIC file to get the default date format of the system. - (See documentation of JIC Language for details on how to call static methods from JIC files)
- For example,
-
Define all the date formats in the same file and use build parameters and the
switch
structure for choosing a one them. (See documentation of JIC Language for details)
-
No changes to the application code are needed to configure the
DateFormat
further. We could also specify the time zone and date format symbols of the date format in the JIC file.
3. Why Not Just Do Everything in Java Code?
Everything JICE does may be achieved by writing Java code. However, JICE makes the definitions of the application objects easier to change and manage:
-
The content in the JIC files is simpler than Java code - it does not contain any complex logic such as if-else and loop structures, try-catch blocks, etc. Therefore:
- The developer is forced to organize the application into independent building blocks or modules from which the application is assembled.
- The XML files are easier to change than Java code.
- The JIC files provide a better insight to the structure of the application than Java code.
- The XML content does not have to be recompiled. It can be manipulated also during application lifetime.
- The configuration is in XML format and may be manipulated with XML tools.
4. Using JICE for Constructing Applications
A running Java application consists of Java instances. Application construction is a process where these Java instances are created, their state is initialized and the necessary objects are connected with each other.
The process consists mainly of multiple constructor and method invocations which are executed more or less in sequence. New Java objects are instantiated, their properties are set, methods are called, object references are passed around, etc.
JICE is an engine that performs these construction tasks. It specifies an XML language called JIC Language for describing the kind of Java instances an application has. JIC Engine is a set of Java classes for processing the XML data. JIC Engine reads the instructions in an XML file and initializes the necessary Java instances by using reflection.
4.1. Application Construction Model
The following chart gives an overview of the application construction process.
Here is a explanation of the details:
- A JIC file contains the construction instructions that are written in JIC Language. The instructions specify what kind of Java instances are to be created.
- In addition to the JIC file, some runtime parameters may be provided. These parameters are Java instances created outside JIC Engine.
- Classpath contains all the available Java classes and therefore specifies the kind of Java objects that can be created.
- JIC Engine reads the instructions of the JIC file and creates the required Java objects with reflection.
- The result of the process is a graph of Java objects. The graph can be a whole application or it may be used as a part of a larger application.
4.2. Why Use JICE in Application Construction?
- JICE specifies a model for application construction. It is easier to understand how the application objects are initialized and when.
- JICE collects all the construction instructions into a central location - an XML file. Construction details are easier to modify when the information is not scattered in many classes.
- The XML file provides a common context for all of the objects. Object references are easy to pass around.
- JICE does not require anything special from the application classes - instance of any Java class can be initialized.
- Dependies of the application classes are easy to manage. JICE supports the Dependency Injection pattern, for more information see:
- Martin Flower. 2004-01-23. Inversion of Control Containers and the Dependency Injection pattern. http://www.martinfowler.com/articles/injection.html.
- JIC Language provides an easy format for encoding construction instructions. The constructions details are easy to change.
- The elements in the XML file correspond to the Java instances in the application, so the tree hierarchy formed by the XML elements visualizes the structure of the application.
5. Using JICE for Configuring Applications
In addition to application construction, JICE can also be used in application configuration. Application construction and configuration are closely related, as the construction usually includes configuring the application.
5.1. What Is Application Configuration?
In this context, configuring an application means modifying some parts of an application without touching the actual application code. It is in contrast with programming, which definitely includes the modification of the source code.
In addition to the actual code, applications typically have various kinds of configuration files that specify some details of the application. Traditionally the configuration files contain minor details like fonts, colors, localized texts, etc. An application is configured by editing these configuration files.
In general, configuration files are used because there is a need to change some parts of an application easily. Application code is often not flexible enough - it has to be compiled, the editing requires programming skills, etc.
An application using configuration files consists of:
application = application code + configuration data
There is no clear rule on how to decide what things should be configurable and what things should be put in application code. The minor details are a good candidate for configurable things - putting detailed values into the code is considered hardcoding, which is a bad thing in general. The implementation of the core application logic and features should be defined in the application code. However, there is a gray area between these two things.
5.2. Why Use JICE for Configuring Applications?
In general, JICE is suitable to be used as a configuration tool because the instructions in the JIC files are easier to change than Java code:
- The information is interpreted. No recompilation is needed.
- JIC files do not contain complex logic. The content is easier to understand than Java code, which makes it safer to edit the JIC files.
- The XML format is verbose. This enhances the readability of the content.
As a configuration tool, JICE provides four things:
- a flexible format for specifying the details of the application
- the possibility to implement also larger structure changes without code changes
- modification of application configuration with XML tools such as XSLT
- there is no need to document the configuration. There is a direct mapping between the JIC file and the application API, so it is enough to only document the Java API.
The JIC Language is a good format for describing details: strings, numbers, booleans, urls, file paths, colors, fonts, date and number formats, etc. The format is very verbose and declarative, so it is relatively easy to both find the value to be modified and modify the value without breaking anything.
However, in addition to the specific data values, a JIC file defines also some parts of the application structure. This has both pros and cons. The format enables even complex structure changes, which is typically not possible with other configuration tools like Java properties files for example. On the other hand, the content in a JIC file is more complex than in a configuration tool that is specialized in specifying only the details - Java properties files are as simple as it can get.
The fact that JICE uses XML files brings in all the advantages of XML. It is for example possible to modify the configuration of an application with XSLT. It is also possible to create a custom XML format for the application and convert it to JIC Language code through XSLT.
6. Things JICE Can Not Do
- No mapping from Java to XML - JICE is not a Java-XML binding tool. There is a mapping from XML to Java, but no reverse mapping.
- new Java classes can not be specified - JICE can only create Java instances of existing Java classes.
- The XML format is fixed - Only JIC Language is supported. However, you could generate the JIC Language code from some other XML format by an XSL transformation.
-
No support for complex logic - JICE has primitive
if
andswitch
structures but the actual application logic must be put in Java classes. - no exception handling - JICE can call Java methods, but can not catch or throw exceptions by itself.