Iron Speed

Recently I had half day available to look into IronSpeed, free edition. For future reference, will write here the key findings.

From the product point of view

– Professional, installs easily, small size of the download

– Installation found installed VS2010 and integrated with it seamlessly

– Tutorials, presentations, web-site usability – all deserve best marks.

Development

– First steps and creating an application from scratch turned out to be easy (in fact, First Steps tutorial is not really necessary, everything is intuitive). Oracle db connection was established seamlessly

– Created pages were fully functional for CRUD on all connected tables

– Additional plus – programmatic primary and foreigh keys (no idea about the performance impact of those)

– Workflow is not available in the free version, but aparently is mainly based on email notifications about the stages of the project cycle

Difficulties

Well, after the initial CRUD application further customizations did not seem to be better than in any other IDE. I fact I found it easier to do it in VS, as I’m more used to it and it has Sharpener to help with code-autocompletion, search, syntax etc. From the other point of view, opening and editing the application in VS was no issue.

The structure of the generated code seems very reasonable and clear, with separate libraries for Business Logic, Data Acccess etc.

Conclusion 

Though IronSpeed won’t replace you your plain, reliable coding skills, it can speed up the initial development  and setup or even generate all the code for simple typical applications.  Compared to standard VS templates it brings in immediate integration with the database and offers page generation tools.

In one sentence: give it a try!

Leave a comment

Liferay with Oracle XE

Well, that’s not a rocket science, but just a few simple tips for installing liferay 6 to work with oracle XE.

First you need to

Tune up your Oracle XE instanse:

use command-line:

type

sqlplus system

enter password

SQL> alter system set sessions=250 scope=spfile;
SQL> alter system set processes=200 scope=spfile;

SQL> shutdown immediate // or restart the database using any other ways you know: from the Oracle XE menu, from system services or whatever

This info is taken from here:

http://kishantha.blogspot.com/2009/03/increase-sessions-and-processes-of.html

Then create a user lportal with a passwork lportal and give this user DBA rights and all permissions.

Setup Oracle as your Liferay Database:

in ..\liferay-portal-6.0.5\tomcat-6.0.26\webapps\ROOT\WEB-INF\classes create file portal-ext.properties:

#
# Oracle
#
jdbc.default.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.default.url=jdbc:oracle:thin:@localhost:1521:xe
jdbc.default.username=lportal
jdbc.default.password=lportal

Find ojdbc14.jar in your Oracle XE folder and copy it to ..\liferay-portal-6.0.5\tomcat-6.0.26\webapps\ROOT\WEB-INF\lib

More detailed info here:
http://www.liferay.com/web/guest/community/wiki/-/wiki/Main/Database%20Configuration

Leave a comment

Vaadin-Liferay-Netbeans-Maven

Just posting here this example. Maybe somebody will find it useful. This project does absolutely nothing, but contains the configuration and works (somehow):

http://www.4shared.com/file/OHoOjtCR/vaadindemo.html

Of course, Maven -3.0.1, liferay-6.0.5, vaadin -6.4.8, netbeans-6.9.1 are supposed to be there. Well, I guess it might work with the other versions too..(i.e. miracles happen!)

And now with Portlet Edit mode! Yay!

http://www.4shared.com/file/jRGYq1nn/vaadindemo_with_edit.html

Leave a comment

XP Forum in JHB

Yesterday we had an interesting event in Wits university  –  a presentation about implementing XP in customer contracts. Looks like making a contract can be a real challenge, but that’s the only way to go. The suggested model for XP: fixed cost contract. The idea is to disclose your costs and expected profit to the customer, set a target time and define the scope on a very-high level. The high-level definition of the scope allows both parties to negotiate on the specific module (requires lots of trust).  Disclosing your costs&profits is supposed to improve the trust relationship. The negotiation on modules is certainly something not clear enough, especially if the client in the beginning has no idea of what they want (which is often the case).

Otherwise, I feel quite scared, – probably writing software on demand is very risky. I’m rather looking at SaaS.

, ,

Leave a comment

Make Your Program Write Code For You

I’m back to writing PLSQL and it’s pain as always. Recently I was dealing with the issue of synchronizing table data between 2 databases and needed to provide a comparison report about the values that do not match. Well, that’s easy: select rows locally and over the dblink and compare the data. But… what if there are 40 different tables to compare and hundreds of selection criteria to get the data? And no, I do not have time to type it all.

So I needed some sort of automation. Of course PLSQL provides something:

I can use one procedure to populate collections using the selection criteria;

another procedure can check the same primary keys exist in the local and remote collection;

and the last one can browse through a pair of collection rows to compare that all fields have the same values.

That sounds reasonable and short. But each collection should represent a row in a table (something like MyTable%rowtype), that means that collections for different tables will be completely different. So how to make it generic (especially in the case when all fields are to be compared)?

I did not found any elegant answer in PLSQL and typing code for all table variations seemed to be impossible. I had to look for a better solution and I decided to use code patterns and replace pieces that do not match. Thanks to StringTemplate the work turned to be really easy. StringTemplate allows separation of your code from the template code. The benefit here is that the template looks semantically the same as the result, so it is very easy to create, correct and maintain. In the same time the code stays clean and very simple. Though StringTemplate has a rich API, I basically mastered only a small piece of it in 5 minutes and that was far enough to do the entire job.

For those who are still interested, here is an example.

Example

Imagine we have a list of tables (Table1, Table2, Table3 for instance) in 2 databases connected over a db link; the tables can have any amount of fields with different names. Our goal is to compare all the values in matching tables between 2 databases, i.e. first we will check that all IDs from local database table are present in the remote table and then we will compare that the rows with the same ID have all other fields with the same values.

To make it shorter let’s imagine that the code populating data into Table1%rowtype (Table2%rowtype, Table3%rowtype etc) collections is already generated. So we will need the following templates (I’ve started by writing this code manually for 1 table to be sure about the template syntax):

Templates

In all the templates below $$ is used to distinguish a replaceable attribute.

compare.st – Top-level checking function:

———————————————————————

procedure $compare_procedure_name$($local_table$ $table_type$,
$remote_table$ $table_type$) is

rec_id integer;
column varchar2(30);
begin
for i in 1 .. $local_table$.count
loop
rec_id := $find_procedure_name$($remote_table$, $local_table$(i).id);
if rec_id < 0 then
log_error(‘Missing $entity_name$: ‘|| $local_table$(i).id);
error_count := error_count + 1;
else
if not $compare_function_name$($local_table$(i), $remote_table$(i), column) then
log_error(‘Different values observed in $entity_name$.’ || column || ‘:’ ||$local_table$(i).id);
error_count := error_count + 1;
end if;
end if;
end loop;
end;

find.st Function to locate a matching record in a collection

function $find_function_name$($generic_table$ $table_type$, $entity_id$ varchar2)
return integer
is
begin
for i in 1 .. $generic_table$.count
loop
if $generic_table$(i).id = $entity_id$ then
return i;
end if;
end loop;
return -1;
end $find_function_name$;

compare_row.st Function to compare a selected row

function $compare_function_name$(local_entities edh_core.$entity_name$%rowtype,
remote_entities edh_core.$entity_name$%rowtype,
column out varchar2) return boolean
is
begin
$compare_declarations$
return true;
end $compare_function_name$;

compare_field.st A piece of code to compare a single field value:

if local_entities.$field_name$ <> remote_entities.$field_name$ then
column := ‘$field_name$’;
return false;
end if;

Filling the templates

Now that the templates are ready, we will only need to apply them for all tables and fields and write to a file (I used a package template too, which you can easily create yourself).

General way to call a template:

// Templates are stored in templatesFolder
StringTemplateGroup group = new StringTemplateGroup(“GroupName”,
“templatesFolder”, DefaultTemplateLexer.class);

You can make group variable a class field as it will be used in all the template-handling procedures.

// compare is the name of template file without “.st” extension
StringTemplate procedure = group.getInstanceOf(“compare”);

Now we need to set all the attributes used in the template

// Compare procedure name can be generated based on table name and selection criteria: compare_table1_description, compare_table2_time etc
procedure.setAttribute(“compare_procedure_name “, “compare_” + tableName + “_” + criteria);
procedure.setAttribute(“local_table”, tableName + “_local”);
procedure.setAttribute(“table_type”, “t_” + tableName);
procedure.setAttribute(“remote_table”, tableName + “_remote”);
procedure.setAttribute(“find_procedure_name”,“compare_” + tableName + “_” + criteria);
procedure.setAttribute(“entity”, tableName + “_remote”);
// You can type the result or return it as the function result
System.out.println(procedure.toString());
return procedure.toString();

In an analogous way you can get the result from find.st template.

A bit more work is to use compare_row and compare_field templates, as compare_field template must be used inside compare_row as many times as there are fields in a row:

public String generateCompare() {
StringTemplate procedure = group.getInstanceOf(“compare_row”);
procedure.setAttribute(“compare_function_name”, getCompareProcedureName());
procedure.setAttribute(“entity_name”, tableName);
procedure.setAttribute(“compare_declarations”, getCompareTemplate(tableName));
System.out.println(procedure.toString());
return procedure.toString();
}

public String getCompareTemplate(String tableName) {
if (entityName == “Table1”) {
return getCompareTemplate(new String[]{“Table1Field1″, ” Table1Field2″, ” Table1Field3″});
} else if (entityName == “Table2”){
return getCompareTemplate(new String[]{“Table2Field1″, ” Table2Field2″});
} else if (

///………

}
return “”;
}

private String getCompareTemplate(String[] fields) {
String compares = “”;
for (int i = 0; i < fields.length; i++){
StringTemplate template = group.getInstanceOf(“compare_field”);
template.setAttribute(“field_name”, fields[i]);
compares += template.toString() + “\r\n”;
}
return compares;
}

Now instead of typing all these procedures for all the tables, you can just specify which table you are interested in, and then pass the columns array to getCompareTemplate.

In this example I do not show how to put all the procedures and functions together in a PLSQL package file and how to fill table rows collections. However, you will be able to add those simple templates yourself and write the result into *.pck file.

In general StringTemplate can save you lots of copy-pasting work and help to tame PLSQL, html, xml and other code.

Leave a comment

Using a Database Over a Webservice

Download source code – 780 kB

Introduction

RemotingService project was developed as a simple proof of concept (the idea taken
from Database as a Webservice). It is just one more way to realize a remote persistence.

In fact, putting any database on a web-server and providing a remote user interface to it, will realize the same idea from a user point of view. The interesting point of this solution is in the fact that no extra interface is developed, actually database interface is just transferred over the network.

This realization is possible due to the simple object-oriented interface provided by db4o database.

A possible implementation can be in providing personal web-based databases for remote
customers. Assuming that each user will use only one and his own database, this solution seems to be viable, providing the data is personally encrypted and unique database names are used.

Background

This article was inspired by Krispy Blog.

Solution Organization

RemotingXml consists of 4 projects:

  • Db4objects.Db4o: db4o open-source database. Please, refer to db4o.license.html for licensing information. The code was slightly modified, which will be discussed later.
  • Server: contains the code for a remote server. Server project is responsible for creating and starting remoting services.
  • RemotingExample: contains the code for creating persistent objects, sending them for serialization to the server and requesting the server for objects from the database.
  • RemotingClasses project is a library containing the definitions for classes to be
    persisted.

Remoting Classes

RemotingClasses project contains only one test class, which will be used on the client to be stored on the server. The class must have Serializable attribute to be transferrable over the network:

[Serializable]public class TestValue

{

…

}

db4o Database Amendments

In order to send the persistent classes from the client to the server we will need a Marshal-By-Reference object. This can be any class providing access to an ObjectContainer (can be modified ObjectContainer itself). The requirements to the transport object:

  • the transport object should open a database file on request (filename should be provided somehow);
  • the transport object must have zero-parameters constructor.

With the first implementation I tried to modify the ObjectContainer interface and the implementing classes. However it resulted in quite a lot of modifications as the hierarchy is
deep. Moreover, I could not find a logical place to pass a filename to the object container (default implementation requires it in the constructor, and our rules need a parameterless constructor).

In the implementation, provided in this example, I use a version of Db4oFactory class, which can work over the network and can provide ObjectContainers for client requests:

using System;
using System.IO;
using Db4objects.Db4o;
using Db4objects.Db4o.Config;
using Db4objects.Db4o.Ext;
using Db4objects.Db4o.Foundation;
using Db4objects.Db4o.Foundation.Network;
using Db4objects.Db4o.Internal;
using Db4objects.Db4o.Internal.CS;
using Db4objects.Db4o.Reflect;

namespace Db4objects.Db4o
{
    ///
    /// This class simply duplicates Db4oFactory with
    /// instance methods, thus allowing Marshalling to
    /// access them
    ///
	public class Db4oRemoteFactory: MarshalByRefObject
	{
		internal static readonly Config4Impl i_config = new Config4Impl();

		public  IConfiguration NewConfiguration()
		{
            		return Db4oFactory.NewConfiguration();
		}

		public IConfiguration CloneConfiguration()
		{
			return (Config4Impl)((IDeepClone)Db4oFactory.Configure()).DeepClone(null);
		}

		public  IObjectContainer OpenFile(string databaseFileName)
		{
			return OpenFile(CloneConfiguration(), databaseFileName);
		}

		public IObjectContainer OpenFile(IConfiguration config, string databaseFileName
			)
		{
			return ObjectContainerFactory.OpenObjectContainer(config, databaseFileName);
		}

	}
}

This implementation is convenient for clients working separately. However, it is not suitable for concurrent collaborative work on the same database file.

Another important change to the db4o sources: some of the internal classes representing persistent objects were marked [Serializable] to be suitable for over-network transmission.

Server

The Server project is presented by a single Program class, which role is to start Db4oRemoteFactory service:

    class Program
    {
        static void Main(string[] args)
        {
            // Setting up tcp channel
            BinaryClientFormatterSinkProvider clientProvider = null;

            BinaryServerFormatterSinkProvider serverProvider =
                new BinaryServerFormatterSinkProvider();

            serverProvider.TypeFilterLevel =
                System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

            IDictionary props = new Hashtable();

            /*
             * Client and server must use the SAME port
             * */
            props["port"] = 65101;
            props["typeFilterLevel"] = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

            TcpChannel chan =
                new TcpChannel(props, clientProvider, serverProvider);

            ChannelServices.RegisterChannel(chan);

            Type TestFactory = Type.GetType("Db4objects.Db4o.Db4oRemoteFactory, Db4objects.Db4o");
            RemotingConfiguration.RegisterWellKnownServiceType(
                    TestFactory,
                    "TestFactoryEndPoint",
                    WellKnownObjectMode.Singleton
                );
            Console.WriteLine("TestFactory is ready.");

            // Keep the server running until the user presses
            // the Enter key.
            Console.WriteLine("Services are running. Press Enter to end...");
            Console.ReadLine();
        }
        // end Main

    }

Client

Client project contains Program class.

In the constructor a connection to the Db4oRemoteFactory service is established:

      public Program()
        {
            string url;

            // Setup a client channel to our services.
            url = @"tcp://LocalHost:65101/";
            BinaryClientFormatterSinkProvider clientProvider =
                new BinaryClientFormatterSinkProvider();

            BinaryServerFormatterSinkProvider serverProvider =
                new BinaryServerFormatterSinkProvider();

            serverProvider.TypeFilterLevel =
                System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

            IDictionary props = new Hashtable();
            props["port"] = 0;
            props["name"] = System.Guid.NewGuid().ToString();
            props["typeFilterLevel"] = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

            TcpChannel chan =
                new TcpChannel(props, clientProvider, serverProvider);
            ChannelServices.RegisterChannel(chan);

            // Set an access to the remote proxy
            factory = (Db4oRemoteFactory)RemotingServices.Connect(
                typeof(Db4oRemoteFactory), url + "TestFactoryEndPoint"
                );
        }
        // end Program

The RunTest method creates a test object, sends it to the server using factory and retrieves it from the database on the server:

        private void RunTest()
        {
            // Remote persistent class
            TestValue testValue;
            testValue = new TestValue();
            // Modify local TestValue object
            testValue.ChangeData("Test value");
            // Pass testValue to the server through testServer
            // and store the testValue object
            IObjectContainer testServer = factory.OpenFile("test.db4o");
            testServer.Set(testValue);
            // Test what is stored to the database
            IList result = testServer.Get(typeof(TestValue));
            //TestValue test;
            foreach (TestValue test in result) {
                System.Console.WriteLine(test);
            }
        }
        // end RunTest

Points of Interest

  • The most interesting TO-DO on this project is, of course, its performance. How much information is transferred over the network for a single request? How is it comparable to the client-server version of db4o?
  • Are there any advantages over client-server version of db4o?
  • This implementation can only work over tcp-channel. Is it possible to realize the same functionality over html-channel?
  • How to realize concurrency control?

History

2007-05-28 First version.

Leave a comment

Marshal By Value for Persistence

I was recently writing about how to use Marshal By Value with db4o and was very surprised how little information could I found on this actually simple subject.

So, to contribute to the global network – here is another Marshal By Value example, this time with xml.

Download RemotingXml.zip – 11.3 KB

Introduction

RemotingXml project was
developed with 2 purposes in mind:

  • show how to use marshal
    by value technology;
  • show how to implement a
    remote storage.

RemotingXml project consists
of a client and a server. The client creates and works with objects and sends them
to the server using marshal-by-value technology to be stored to XML files. The client
is also able to request the objects from the XML files.

This project might be helpful to those, who want to implement some kind of remote
persistence solution. In this example, XML files are used as a very simple and comprehensive
example, however the project can be easily used as a template to build a database
or file-based remoting storage solution.

Background

Though marshal-by-reference
remoting is widely covered on the net, marshal-by-value still tends to create some
confusion. This project is created to clear up this confusion and show an example
of how marshal-by-value objects can be used.

Solution Organization

RemotingXml consists of
3 projects:

  • Server: contains the code
    for a remote server. Server project is responsible for creating and starting remoting
    services.
  • Client: contains the code
    for creating persistent classes, sending them for serialization to the server and
    requesting the server for objects from the XML files.
  • PersistentClasses project
    is a library containing the definitions for classes used on the client and on the
    server. These include: class to be serialized, list wrapper for the serialized class
    and marshal-by-reference class used for persistent classes transport.

Persistent Classes

Persistent classes are the
classes that will be created on the client and serialized on the server. Any class
can be persisted if it either has Serializable attribute
or implements ISerializable interface. In this example,
House and Address classes are used.

Address class is saved as
a field in the House class:

[Serializable]
public class House
{
private Address _address;

private string _owner;
….
}

In order to save a list of houses we will need to create a special List implementation:

[Serializable]

[XmlInclude(typeof(House)), XmlInclude(typeof(Address))]

public class HouseList : List

{

}

This implementation is required for 2 purposes:
An object passed to a remote server should be serializable
The object need to provide the details of included classes for correct serialization.

Transport Class

In order to send the persistent
classes from the client to the server we will need a Marshal-By-Reference object:

    public class XmlHandler: MarshalByRefObject

    {

        private const string Extension = ".xml";

        // list of remote objects

        private IList _persistentObjects;        public IList PersistentObjects

        {

            get { return _persistentObjects; }

            set { _persistentObjects = value; }

        }

        // end PersistentObject

public void StoreData()

        {

            // Serialize object list to xml

            System.Console.WriteLine("persistentObjects " + _persistentObjects.Count);

            if (_persistentObjects.Count > 0)

            {

                // define the object type

                object persistentObject = _persistentObjects[0];

                XmlSerializer serializer = new XmlSerializer(_persistentObjects.GetType());

// delete the old file and create a new one

                string filename = persistentObject.GetType().Name + Extension;

                File.Delete(filename);

                StreamWriter xmlWriter = new StreamWriter(filename);

                // serialize object list

                serializer.Serialize(xmlWriter, _persistentObjects);

                xmlWriter.Close();

            }

        }

        // end StoreData

public IList RetrieveData(Type arrayType, Type objectType)

        {

            // Compose the file name

            string filename = objectType.Name + Extension;

            // deserialize

            XmlSerializer serializer = new XmlSerializer(arrayType);

            FileStream xmlFileStream = new FileStream(filename, FileMode.Open);

            IList objects = (IList)serializer.Deserialize(xmlFileStream);

            xmlFileStream.Close();

            return objects;

        }

        // end RetrieveData

    }

XmlHandler
holds a reference to the persistent objects array in _persistentObjects variable.
This variable is passed from the client.

As you can see there are methods for serializing and deselializing objects. These
methods are executed on the server.

Server

The Server project is presented
by a single XmlServer class, which role is to start XmlHandler service

    class XmlServer

    {

        static void Main(string[] args)

        {

            // Setting up http channel

            HttpChannel channel = new HttpChannel(65101);

            ChannelServices.RegisterChannel(channel);            Type XmlHandler = Type.GetType("RemotingXml.PersistentClasses.XmlHandler, PersistentClasses");

            RemotingConfiguration.RegisterWellKnownServiceType(

                    XmlHandler,

                    "XmlHandlerEndPoint",

                    WellKnownObjectMode.Singleton

                );

            Console.WriteLine("XmlHandler is ready.");

// Keep the server running until the user presses

            // the Enter key.

            Console.WriteLine("Services are running. Press Enter to end...");

            Console.ReadLine();

        }

        // end Main

    }

Client

Client project contains Program class.
In the constructor a connection to the XmlHandler service is established:

        public Program()

        {

            string url;            // Setup a client channel to our services.

            HttpChannel channel = new HttpChannel(0);

            url = @"http://LocalHost:65101/";

// Register the channel

            ChannelServices.RegisterChannel(channel, false);

// Set an access to the remote proxy

            xmlHandler = (XmlHandler)RemotingServices.Connect(

                typeof(PersistentClasses.XmlHandler), url + "XmlHandlerEndPoint"

                );

        }

        // end Program

The RunTest method creates
a list of House objects, sends them to the server using XmlHandler and retrieves
the objects from the XML files on the server:

        private void RunTest()

        {

            // an object to be stored remotely

            House house = new House(new Address("East London", "266 Oxford Street"), "Derick Hopkins");

            // Create a list to hold House instances

            HouseList persistentObjects = new HouseList();

            persistentObjects.Add(house);

            // another House for a list

            house = new House(new Address("East London", "23 Stewart Drive"), "Om Henderson");

            persistentObjects.Add(house);

            // Pass House list to the server using XmlHandler

            xmlHandler.PersistentObjects = (IList)persistentObjects;

            // Call method on the server to store houses to an XML file

            xmlHandler.StoreData();

            // Test what is stored to the database

            IList result = xmlHandler.RetrieveData(typeof(HouseList), typeof(House));

            foreach (object obj in result)

            {

                System.Console.WriteLine(obj);

            }

        }

        // end RunTest

Points of Interest

Creating this project I
had an idea in mind to make it completely generic by using generics for persistent
object collections. However, the idea was not realized due to the fact that Soap
serializer does not support generics and explicit using of binary serializers on
the client and the server still does not solve the problem.

History

2007-05-25 First version.

Leave a comment