Welcome!

Welcome to a simple introduction of the Hypas application server framework. This introduction follows a simple implementation from the code to configuring the application.

top

Lets break the ice

Hypas is as much about the code as about configuration. The configuration file is given as a parameter to the main method of the hypas main class (org.hypas.Kickstart). The hypas consists of two types of configuration types; Modules and Pojos. Modules implement a lifecycle interface and pojos don't. Pojos can be used to configre factory instances and datasources.

Ok, our task is to create an application that takes data from a table/view in a database and publishes the data either as either a csv file or as an excel file. It should be configurable by the user, based on his needs.

Before we dwelwe into code, lets go a little into the api and figure out what it contains.

top

The api

The hypas contains an interface (called org.hypas.Module) and an adapter class (org.hypas.ModuleAdapter) which implement all the methods of the interface.

Using the adapter is recommended, but if your class has to extend some other class, you need to implement theorg.hypas.Module interface instead.

So now we know that we have to either implement an interface or extend a class. We go for extending the class:

package org.hypas.example; import org.hypas;
public class DataFetch extends ModuleAdapter {
// Private members. private DataDestination destination = null; private Datasource data = null;
@override public void init(Element cfg) {
// Check that all members are properly set. // Otherwise throw an exception. if( destination == null ) { throw new Exception("Data destination not set in configuration!"); } if( data == null ) { throw new Exception("Data source not set in configuration!"); }
}
@override public void destroy() {
...
}
@override public void start() {
// Lookup data through datasource. // call destination's open, writeRecord, then close methods.
}
@override public void stop() {
...
}
public void setDataDestination(DataDestination dest) {
destination = dest;
}
public DataDestination getDataDestination() {
return dest;
}
public void setDatasource(Datasource ds) {
data = ds;
}
public Datasource getDatasource() {
return data;
}
}
top

Further on

Now we have mentioned an interface in the above class, which is called DataDestination. This is a simple interface which has three methods.

public interface DataDestination {
public void open(String file);
public void close();
public void writeRecord(ResultSet record);
}

There will be two implementation of this interface. One for excel and one for csv, thus:

public ExcelDestination implements DataDestination {...}
and
public CSVDestination implements DataDestination {...}

Now we hypotetically assume that we have implemented everything. Lets move onto the configuration.

top

The configuration

The configuration file is based on xml, and as explained earlier, it is the second heart of the hypas framework. From the configuration file, the application can be assembled to work as the user wishes. The xml consists of a root module, and its child modules (which again can have their own child modules, but not in this example). This is a simple interface which has three methods.

Lets see the configuration of our application.
<Module name="root"> <Module name="log4j" startOrder="-1" class="no.carrot.hypas.modules.Log4JModule"> <Property name="configuration" value="log4j.xml"/> </Module> <Pojo name="excel" class="org.hypas.example.ExcelDestination"/> <Pojo name="csv" class="org.hypas.example.CSVDestination"/> <Pojo name="productiondb" class="com.microsoft.sqlserver.jdbc.SQLServerDataSource"> <Property name="URL" value="jdbc:sqlserver://10.0.0.10:1433"/> <Property name="user" value="sa"/> <Property name="password" value="admin"/> </Pojo> <Pojo name="alternative" class="com.microsoft.sqlserver.jdbc.SQLServerDataSource"> <Property name="URL" value="jdbc:sqlserver://10.0.0.20:1433"/> <Property name="user" value="sa"/> <Property name="password" value="admin"/> </Pojo> <Module name="fetcher" class="org.hypas.exampple.DataFetcher" startOrder="1"> <Property name="datasource" link="/root/productiondb"/> <Property name="destination" link="/root/csv"/> </Module> </Module>

At the top, there is a Module definition. If there is no class attribute of the Module tag, a default Module is instantiated. This top module is named "root". Almost all the time, there will be a top module like this. There might be implemented custom top modules which perhaps autoreconfigures its children, or autodeployes modules from a jar file etc. There are many possibilities that are not yet explored.

Ahem, back to track. The first child in the root module, is a built in module, that configures log4j from a configuration file. The Property tag that the Module contain, causes the setter method of the class to be called. The "setConfiguration" method will be called. The parameter conversion will occur automatically. All native types, and String will be autoconverted. There is however no restrictions of what the Modules children can be. But only the Propery tag trigger an action within hypas. The full xml section of the module will come as a parameter in its init method (as you saw above, hopefully).

The next two children of the root module, is two pojos. They are the ones we created (fictionally atleast). They don't need any lifecycle so they are created as pojos. The objects get created right away, as the hypas initializes and reads the configuration.

Then there are two datasources that gets configured, in the same manner as the two DataDestination classes. Their properties are set automatically by hypas.

Then at the end, is our DataFetcher class configured. As we see, it gets two properties set on it. A datasource, and a DataDestination. The difference here from the normal Property tag is that we link modules. Instead of using value attribute, we use a link attribute, and thus tells hypas that the value is a reference to a module/pojo that is configured in the configuration file. It uses a path like structure to find the module/pojo. So the setDatasource method is invoked by hypas with the productiondb datasource instance as parameter, and the setDestination with the csv DataDestination object as parameter.

top

Result

What will happen? Well, first off the rootmodule gets instantiated. If it had any Property tags, they would have been set. Then the root module's children get instantiated, one by one. Then their properties gets set. After all modules and pojos have been instantiated and properties set, the init is called on the root module. This causes init to be called on all child modules. Then only the modules that have a startOrder higher than 0 gets started (start method gets called). Lowest startorder gets started first and so on.

The stop and destroy is called recursively on the root module, by a shutdown hook. So if no non daemon threads threads are started and the main thread dies. THe hypas destroys everything and returns to the operating system.