My two cents of Bitcoin

June 19, 2011

Last week a friend recommended Bitcoin, as a novel peer to peer technology and currency. Well, I installed the software, I benchmarked my workstation by mining 0.04 units of currency. But the biggest accomplishment was understanding the mechanism of the currency. Here I see a big issue; if the politicians will not be able to understand how it works, will ban the technology in a defensive movement. If the people won’t understand how it works, they won’t trust the coin. Fiat currency (meaning, currency without intrinsic value, opposite to golden coins) only exist because of people using it are educated: they know they can redeem the paper money in goods or services, and the government (or better said, the national bank) guarantees it. Imagine Cesar trying to pay his brave solders with fiat money.. he would have generated a riot so large, because even with his established authority, the people were not enough educated, or experienced, to accept this. So even today, it may take generations until the large masses will trust the Bitcoin.

The major issue of Bitcoin is the issuer. The coin is dis-centralized, but there is an issuer, meaning there is a way to produce money out of thin air. The mechanism of distributing the coins is relatively rigorous, the block generators receive the credit for their hard computational work. The problem is that somebody has the authority to issue new coins. If this person becomes greedy, the market will be flooded by new coins, in time the trust in the coin will erode, but the issuer will get very rich. And since this is not an official currency, the law will be unable to prosecute the issuer. A way to avoid this would be an accounting of new money issued, by each client. Any discrepancy with the known issuing scheduler should generate a warning in each wallet application, since this inflationist happening will dilute everybody’s value, or even better, the peer to peer clients should act as financial controllers of the issuing authority, and oppose any attempt of issuing more bitcoins than scheduled.

Another issue is the wild value variation. The national bank of every country is preoccupied of keeping its currency stable. This means, the regular Joe should not experience from month to month variations in his income. It is unacceptable that one month one earns a car, but next month is unable to feed his kids. Also, the merchants will not accept the risk of handling volatile currencies, so I assume the currency won’t be widely adopted until it will show some stability. Of course, they can assure themself (by hedging) but how many of you selling t-shirts know how hedging works?

Further, I see the coin unnecessary anonymous and unnecessary non-anonymous. Let’s assume for a minute that the whole galaxy adopted Bitcoin as the only currency. I am buying some goods from a store. By sending them the money, they can learn my whole financial saga, from my birth to now. They know how much I earn, they can eventually identify my employer or competitor sellers I have purchased merchandise from. They may learn where I like to travel, if  I have debts, to whom, how much do I pay rent or mortgage. Even if people believe in total anonymity of the coin, this is not true. As a seller one can easily start compiling a large database of names and Bitcoin, based on shipping addresses, formum adds, etc. And they can exchange data between them, or can even offer this data for sale. Even if somebody is yet unknown to the sellers, knowing other he or she did transact with, can lead to identification of address, preferences, age, etc. The bright side of this is that data mining will flourish trying to understand spending patterns, financial interactions or even the essence of wealth.

If you ask me how do I figure out who send money to whom, imagine the following block:

A  send 1.5

B sends 1.8

C receives 1

D sends 0.5

E sends 0.5

F receives 3.3

Even if not explicit, it is easy for a human, and even easier for a computer, to assert with a good confidence that: A and B send money to F, and, D and E send money to C.

I see an immediate use of BC in cheap goods, such as music, shareware software or tangible goods. This may clear the name of P2P networking when its about software or music piracy.

The Bitcoin software I installed seems to unnecessary use the hard drive (by reading and writing own files). That’s maybe because whole financial history of Bitcoin resides now on my hard drive, too.

For the moment, the users experience free transactions, but in the moment the transaction fee will have to support the generation of blocks, it may be that either a block will have really thousands of transactions, or the users will have to pay a premium fee for an expedite transaction. And if the blocks are large, it will be harder to associate receiver and sender by data mining.

Notes on the Spring-WS tutorial

September 26, 2009

Today I have reviewed a proof of concept I have done in order to decide which Web Services framework matches the requirements of a bioinformatics project. Because of forgetting to store a file in the versioning system, I had to review the whole tutorial and to look for the file within the Spring tutorial. What is interesting, until now nobody published the full content of the Spring-WS tutorial.

So, here is my pom.xml. I am using Apache Maven2 in order to strictly enforce the versions of the JAR files. Nobody is constrained to use Maven, but without it, it would be very difficult to sort out the transient dependencies.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.razvan.hr</groupId>
 <artifactId>holidayService</artifactId>
 <packaging>war</packaging>
 <version>1.0-SNAPSHOT</version>
 <name>holidayService Spring-WS Application</name>
 <url>http://www.springframework.org/spring-ws</url>
 <build>
 <finalName>holidayService</finalName>
 <plugins>
 <plugin>
 <groupId>org.mortbay.jetty</groupId>
 <version>6.1.9</version>
 <artifactId>maven-jetty-plugin</artifactId>
 </plugin>
 </plugins>
 </build>
 <dependencies>
 <dependency>
 <groupId>org.springframework.ws</groupId>
 <artifactId>spring-ws-core</artifactId>
 <version>1.5.8</version>
 </dependency>
 <dependency>
 <groupId>jdom</groupId>
 <artifactId>jdom</artifactId>
 <version>1.0</version>
 </dependency>
 <dependency> <!-- required by AbstractJDomPayloadEndpoint -->
 <groupId>jaxen</groupId>
 <artifactId>jaxen</artifactId>
 <version>1.1</version>
 <scope>runtime</scope>
 </dependency>
 <dependency>
 <groupId>javax.xml.soap</groupId>
 <artifactId>saaj-api</artifactId>
 <version>1.3</version>
 <scope>runtime</scope>
 </dependency>
 <dependency>
 <groupId>com.sun.xml.messaging.saaj</groupId>
 <artifactId>saaj-impl</artifactId>
 <version>1.3</version>
 <scope>runtime</scope>
 </dependency>
 <dependency>
 <groupId>xalan</groupId>
 <artifactId>xalan</artifactId>
 <version>2.7.1</version>
 </dependency>
 </dependencies>
</project>

I am using the jetty plugin in order to be able to run the application right from the command line; xalan dependency is required in order to avoid the exception “java.lang.IllegalStateException: Could not find SAAJ on the classpath” thrown by Spring-WS, corrected in a newer version of xalan.

Also according to the tutorial, the file spring-ws-servlet.xml, a regular Spring context file, describes the external interface of the Web Service and the associated Java classes. This file has to be placed in the src/main/webapp/WEB-INF directory.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

 <bean id="holidayEndpoint" class="com.razvan.hr.ws.HolidayEndpoint">
 </bean>

 <bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
 <property name="mappings">
 <props>
 <prop key="{http://mycompany.com/hr/schemas}HolidayRequest">holidayEndpoint</prop>
 </props>
 </property>
 <property name="interceptors">
 <bean class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor" />
 </property>
 </bean>

 <bean id="holiday" class="org.springframework.ws.wsdl.wsdl11.DynamicWsdl11Definition">
 <property name="builder">
 <bean class="org.springframework.ws.wsdl.wsdl11.builder.XsdBasedSoap11Wsdl4jDefinitionBuilder">
 <property name="schema" value="/WEB-INF/hr.xsd" />
 <property name="portTypeName" value="HumanResource" />
 <property name="locationUri" value="http://localhost:8080/holidayService/" />
 </bean>
 </property>
 </bean>

</beans>

And here is the implementation of com.razvan.hr.ws.HolidayEndpoint. According to Maven customaries, this have to be placed in the src/main/java subdirectory of the project. I have tried to keep the implementation minimal by avoiding further service instantiations, unrelated to Spring-WS:

package com.razvan.hr.ws;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.logging.Log;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.xpath.XPath;
import org.springframework.ws.server.endpoint.AbstractJDomPayloadEndpoint;

public class HolidayEndpoint extends AbstractJDomPayloadEndpoint {

 private XPath startDateExpression;

 private XPath endDateExpression;

 private XPath nameExpression;

 public HolidayEndpoint() throws JDOMException {
 Namespace namespace = Namespace.getNamespace("hr", "http://mycompany.com/hr/schemas");
 startDateExpression = XPath.newInstance("//hr:StartDate");
 startDateExpression.addNamespace(namespace);
 endDateExpression = XPath.newInstance("//hr:EndDate");
 endDateExpression.addNamespace(namespace);
 nameExpression = XPath.newInstance("concat(//hr:FirstName,' ',//hr:LastName)");
 nameExpression.addNamespace(namespace);
 }

 protected Element invokeInternal(Element holidayRequest) throws Exception {
 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
 Date startDate = dateFormat.parse(startDateExpression.valueOf(holidayRequest));
 Date endDate = dateFormat.parse(endDateExpression.valueOf(holidayRequest));
 String name = nameExpression.valueOf(holidayRequest);

 // do something meaningful with the extracted data.
 System.out.println("Start date: "+startDate+" end Date: "+ endDate+" Employee: "+name);
 return null;
 }
}

My final file structure is:

|-- pom.xml
`-- src
 `-- main
   |-- java
   |   `-- com
   |       `-- razvan
   |           `-- hr
   |               `-- ws
   |                   `-- HolidayEndpoint.java
   `-- webapp
     `-- WEB-INF
        |-- hr.xsd
        |-- spring-ws-servlet.xml
        `-- web.xml

The web.xml is pretty standard for Spring applications:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
 version="2.4">

 <display-name>Spring test application</display-name>

 <servlet>
 <servlet-name>spring-ws</servlet-name>
 <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
 </servlet>

 <servlet-mapping>
 <servlet-name>spring-ws</servlet-name>
 <url-pattern>/*</url-pattern>
 </servlet-mapping>

</web-app>

This is the whole Web Service application. In order to run the application try from the command line:

mvn clean install jetty:run

This will compile the war file and start an instance of the jetty web server.

By accessing the address: http://localhost:8080/holidayService/holiday.wsdl you can see the generated WSDL associated to your described web service. While leaving the jetty running, you may attempt to create a client, in order to see the message printed within the invokeInternal method. Following it will be described a Java client, but it is possible to build your client using any other language or platform.

Using the Eclipse wizard create a new empty Java project, than create using the wizard a new “Web Service Client”. Provide the address of the wsdl and you will have a bunch of Java classes describing your web service and the required XML parsers dependencies in your newly created project. Create a new main class in the default package named TestWs.java, with the following content:

import java.math.BigInteger;
import java.util.Date;

import com.mycompany.hr.schemas.EmployeeType;
import com.mycompany.hr.schemas.HolidayRequest;
import com.mycompany.hr.schemas.HolidayType;
import com.mycompany.hr.schemas.HumanResource;
import com.mycompany.hr.schemas.HumanResourceServiceLocator;

public class TestWs {
 public static void main(String[] args) {
 try {
 HumanResourceServiceLocator loc = new HumanResourceServiceLocator();
 HumanResource myserv = loc.getHumanResourcePort();

 HolidayType ht = new HolidayType(new Date(), new Date());
 EmployeeType et = new EmployeeType(new BigInteger("100"), "Razvan",
 "Popovici");
 HolidayRequest req = new HolidayRequest(ht, et);

 myserv.holiday(req);
 } catch (Exception e) {
 e.printStackTrace();
 }
 System.out.println("OK!");

 }
}

Run the class, and you will be able to observe the message in the maven window.

A few conclusions of the test are:

- Spring-WS is a great approach if the schema definitions of the data model already exists.

- The required xalan dependency is a bug in Spring-WS dependency requirements, fortunately Maven made possible the correction.

- The element wsdl:definitions is optional, the tutorial worked without it as well.

Apache Maven

May 24, 2009

I am using Apache Maven 2 to build the most projects i am involved in. It keeps the project minimal, by the concise description of the dependencies through the transient dependency mechanism and it stores the dependent JAR files separately of the project. It integrates nicely with Eclipse (by creating Eclipse projects) and promises an easy way to get night builds and to separate the sources in a team; for security reasons I don’t want all the members of the team to have all the source code of the application.

I foresee an application of Maven dependency resolution in BeanShell. It will be greatly to have a function like Maven.resolveDependency(String groupid, String artifactid,[String version]). This will make use of the local Maven cache or it will connect to the configured maven repositories and it will download the JAR file together with its dependencies. What a great way to use “dependency rich” modules like Apache Fop in short and self containing BeanShell scripts.

On the other hand, daily use of Maven is far away from idyllic. What annoys a lot are the permanent changes that invalidate the previous configurations. Yesterday I have to build a Web Start application for my employer’s Java Swing software application. Of course, I perceived it as a rather routine task, even with special requirement to obfuscate as much as possible of the source code, except of course of the parts being introspected by the various XML parsers or serializers.

First, I have realized that obfuscation is not possible for multiple projects, except if they are united together. The assembly:assembly plug-in was stubborn enough to include the current directory even if I explicitly forbade it. It also created the nice “c:” entry in the JAR file. Fortunately the entry was not recursive, else I would have ended with my whole C drive in the output file. Help came from the FreeHEP plug-in, their implementation shown efficiency and coherence.

Second, finding an obfuscator is not a trivial job. After some tests, yguard shown the best results.

Third, building the Web Start application itself. Some nice guy renamed the group ID of the package from org.codehaus.mojo” to org.codehaus.mojo.webstart”, so basically I have wondered for a few hours why is my configuration not working, why some settings are simply ignored. I figured it out after I have downloaded the sources of the plug-in and tied to debug it. The task of the plug-in is not trivial, it needs to sign all the dependent JAR file involved in the project and to build the JNLP file. Until now I had my own JNLP template, containing a $dependencies macro to avoid listing the dependencies manually. The file was now simply ignored as I moved to the new plugin and I had to spend a lot of time to fix the configuration. The reason I moved to the new plugin was simple: I needed a way to resign already signed JARs and the new plugin seamed to be the only solution.

Other thoughts about Maven: it is full of unexpected issues, such as, lastly:

[INFO] Internal error in the plugin manager executing goal ‘org.apache.maven.plu gins:maven-antrun-plugin:1.1:run’: Unable to find the mojo ‘org.apache.maven.plugins:maven-antrun-plugin:1.1:run’ in the plugin ‘org.apache.maven.plugins:maven- antrun-plugin’
Component descriptor cannot be found in the component repository: org.apache.maven.plugin.Mojoorg.apache.maven.plugins:maven-antrun-plugin:1.1:run.

Well, the plugin was there, it has even worked previously when running the sibling project. The error occured when compiling the parent project. After some efforts to understand the issue I found a forum, here somebody indicate that placing the plug-in in the  pluginManagement” section of the parent project will overcome the issue. This has worked, but I am still frustrated by not having an answer on the question “why?”.

Another point is the AndroMDA code generator. The generator is implemented through a Maven plugin. In winter I have spend some effort to write an educational software consisting in multiple choiche questions. The software was EJB3 based, all entity beans were described in an UML model. The code generator produced all needed beans, with annotations, cascading rules and database configuration file. The problem now is that the generator was as a Snapshot, and now the same version is not working anymore. [error here].

So, what is the future of Apache Maven? Here is my vision:

  • GUI: it should be possible to configure the project and each single plugin through an user interface. It does not need to be fancy but it should be just effective, see ArgoUML. Editing text XML in 21st century is outrageos.
  • Custom project phases. The predefined build / clean / site lists of phases are insufficient for complex projects.
  • Multiple target types. What if the user needs to have multiple JAR versions of the same project, such as “Java 1.5″ or “Java 1.6″ Runtime? Again hardcoding the possible targets as: sources/javadoc/jar is a private club solution.
  • Multiple languages. C/C++/.NET, even if the project flow is orchestrated by the Java engine.
  • Pipelines. It is nice to have a declarative syntax, but some steps have to be procedural. Currently I think I abuse the Ant plugin and/or the “executions” feature of the plugins, to achieve some kind of procedural steps. Forking should be also allowed, as it can greatly increase the build performance, especially on multiprocessor/multicore machines.
  • Atomicity. Each goal of the plugins has to be atomic. Goals like “discover the Philosopher’s Stone, compile the project and interpret Beethoven’s 9th symphony” should be clearly split in their atomic constituents.
  • Easiness of plug-in development. Writing a plug-in should be easy, ant-like. Also the license should allow, if not yet doing it, proprietary code. Also, the parameters of a plug-in should be self-describing, so that the user interface will be able to present the choiches properly. There should be a plugin test framework, to facilitate quality assurance.

The future of MDA

April 15, 2009

I have discovered MDA, through the AndroMDA project, about 4 years ago. The idea of automatically generating some repeated patterns, the amaizing power of generating a database structure, Entity Beans or Hibernate linkage files by only providing an UML diagram model, the capability of keeping a minimal description (the UML document) have all convinced me not only to learn how AndroMDA works, but also to start using it in production.

As for today, I have used AndroMDA in at least 6 distinct projects. I didn’t use the clasical path shown by AndroMDA. I have chosen atomic Maven projects either 100% UML generated or 100% manual. No file was manually changed after generation, this pattern proved to be desastruous in practice.

I am wondering what is the today future of the MDA. As I was warning 5 month ago a developer of ArgoUML about a minor issue, they exclamated “wow, you are still using AndroMDA!”. So what is the next MDA product? Any answers from the community?

The ZK AJAX Library ignores some of the user’s input

February 1, 2009

I have used ZK for a while, building mostly web administrative interfaces. My applications get usually used in the intranet, they rarely get exposure with the open Internet. The distance between the server and the browser is usually a few routers, so they benefit of an especially low latency and wide bandwidth.

Many users reported that sometimes the application fails to perform the instructed task. From time to time, nothing happens when the user pushes a button or chooses an item from a context menu. Although I have first suspected a programming error, the random distribution of this behavior, in various applications, determined me to suspect the ZK engine of this loss of events.

I have designed a simple test application to check this issue:

<window xmlns="http://www.zkoss.org/2005/zul" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.zkoss.org/2005/zul http://www.zkoss.org/2005/zul/zul.xsd"
    xmlns:a="http://www.zkoss.org/2005/zk/annotation" use="Test1"
    id="w1" width="600px" title="Test window">
<button id="b1" label="Increment" onClick="w1.increment()"/>
<separator width="20px"/>
<label id="lbl" value="Not initialized."/>
</window>

The corresponding  Java resource Test1.java is:

import org.zkoss.zul.Label;
import org.zkoss.zul.Window;

@SuppressWarnings("serial")
public class Test1 extends Window {

	public void onCreate() {
		setValue(start);
	}

	public void increment() {
		setValue(++start);
	}

	private void setValue(int v) {
		Label l = (Label)getFellow("lbl");
		l.setValue(Integer.toString(v));
	}

	private int start = 1;
}

This page simply increments a counter as the button is pressed.

Now, I am going to press the button a lot, to find out how many times the system actually records the button was pressed. The best way to test it is to write a unit test module, based on Selenium test framework. The button is clicked, then the test waits for 350 milliseconds to process the request. After this, the label is pooled for the next 3 seconds to update. If it is not updating to the expected value at the end of the 3 seconds, the iteration is considered an error.

import java.util.Date;
import com.thoughtworks.selenium.SeleneseTestCase;

public class IncrementTestCase extends SeleneseTestCase {
	@Override
	public void setUp() throws Exception {
		setUp("http://localhost:8080", "*custom /usr/bin/firefox");
	}

	@Override
	public void tearDown() throws Exception {
		super.tearDown();
		selenium.stop();
	}

	public synchronized void testIncrement() throws Exception {
		int errors = 0;
		selenium.open("/testapp/test1.zul");

		int value = 1;
		for (int i = 0; i != 100; i++) {
			selenium.click("//td[text()='Increment']");
			value++;
			Date start = new Date();
			boolean found = false;
			Thread.sleep(350);
			// 3 seconds waiting time
			while (new Date().getTime() - start.getTime() < 3000) {
				String s = selenium.getText("//span[@class='z-label']");
				if (Integer.parseInt(s) == value) {
					found = true;
					break;
				}
				Thread.sleep(100);
			}
			if (!found) {
				String s = selenium.getText("//span[@class='z-label']");
				System.out.println("Expected: "+ value + " found " + s);
				value = Integer.parseInt(s);
				errors++;
			}
			System.out.println(new Date().toString() + " Errors: "+ errors + " Loops: " + (i+1));
		}
		System.out.println("Errors: "+ errors);
	}
}

The following output results after the execution of the test:

Sun Feb 01 14:03:08 EST 2009 Errors: 0 Loops: 1
Sun Feb 01 14:03:09 EST 2009 Errors: 0 Loops: 2
Expected: 4 found 3
Sun Feb 01 14:03:12 EST 2009 Errors: 1 Loops: 3
Sun Feb 01 14:03:12 EST 2009 Errors: 1 Loops: 4
Sun Feb 01 14:03:13 EST 2009 Errors: 1 Loops: 5
Expected: 6 found 5
Sun Feb 01 14:03:16 EST 2009 Errors: 2 Loops: 6
Sun Feb 01 14:03:16 EST 2009 Errors: 2 Loops: 7
Expected: 7 found 6
Sun Feb 01 14:03:19 EST 2009 Errors: 3 Loops: 8
Sun Feb 01 14:03:20 EST 2009 Errors: 3 Loops: 9
Sun Feb 01 14:03:20 EST 2009 Errors: 3 Loops: 10
Expected: 9 found 8
Sun Feb 01 14:03:23 EST 2009 Errors: 4 Loops: 11
Sun Feb 01 14:03:24 EST 2009 Errors: 4 Loops: 12
Sun Feb 01 14:03:24 EST 2009 Errors: 4 Loops: 13
Sun Feb 01 14:03:24 EST 2009 Errors: 4 Loops: 14
Sun Feb 01 14:03:25 EST 2009 Errors: 4 Loops: 15
Expected: 13 found 12
Sun Feb 01 14:03:28 EST 2009 Errors: 5 Loops: 16
Sun Feb 01 14:03:28 EST 2009 Errors: 5 Loops: 17
Expected: 14 found 13
Sun Feb 01 14:03:31 EST 2009 Errors: 6 Loops: 18
Sun Feb 01 14:03:32 EST 2009 Errors: 6 Loops: 19
Expected: 15 found 14
Sun Feb 01 14:03:35 EST 2009 Errors: 7 Loops: 20
Sun Feb 01 14:03:35 EST 2009 Errors: 7 Loops: 21
Sun Feb 01 14:03:35 EST 2009 Errors: 7 Loops: 22
Expected: 17 found 16
Sun Feb 01 14:03:39 EST 2009 Errors: 8 Loops: 23
Sun Feb 01 14:03:39 EST 2009 Errors: 8 Loops: 24
Sun Feb 01 14:03:39 EST 2009 Errors: 8 Loops: 25
Sun Feb 01 14:03:40 EST 2009 Errors: 8 Loops: 26
Sun Feb 01 14:03:40 EST 2009 Errors: 8 Loops: 27
Sun Feb 01 14:03:40 EST 2009 Errors: 8 Loops: 28
Expected: 22 found 21
Sun Feb 01 14:03:44 EST 2009 Errors: 9 Loops: 29
Sun Feb 01 14:03:44 EST 2009 Errors: 9 Loops: 30
Expected: 23 found 22
Sun Feb 01 14:03:47 EST 2009 Errors: 10 Loops: 31
Sun Feb 01 14:03:48 EST 2009 Errors: 10 Loops: 32
Sun Feb 01 14:03:48 EST 2009 Errors: 10 Loops: 33
Expected: 25 found 24
Sun Feb 01 14:03:51 EST 2009 Errors: 11 Loops: 34
Sun Feb 01 14:03:51 EST 2009 Errors: 11 Loops: 35
Sun Feb 01 14:03:52 EST 2009 Errors: 11 Loops: 36
Sun Feb 01 14:03:52 EST 2009 Errors: 11 Loops: 37
Expected: 28 found 27
Sun Feb 01 14:03:55 EST 2009 Errors: 12 Loops: 38
Sun Feb 01 14:03:56 EST 2009 Errors: 12 Loops: 39
Sun Feb 01 14:03:56 EST 2009 Errors: 12 Loops: 40
Expected: 30 found 29
Sun Feb 01 14:03:59 EST 2009 Errors: 13 Loops: 41
Sun Feb 01 14:04:00 EST 2009 Errors: 13 Loops: 42
Sun Feb 01 14:04:00 EST 2009 Errors: 13 Loops: 43
Sun Feb 01 14:04:00 EST 2009 Errors: 13 Loops: 44
Sun Feb 01 14:04:01 EST 2009 Errors: 13 Loops: 45
Sun Feb 01 14:04:01 EST 2009 Errors: 13 Loops: 46
Sun Feb 01 14:04:02 EST 2009 Errors: 13 Loops: 47
Sun Feb 01 14:04:02 EST 2009 Errors: 13 Loops: 48
Expected: 37 found 36
Sun Feb 01 14:04:05 EST 2009 Errors: 14 Loops: 49
Sun Feb 01 14:04:06 EST 2009 Errors: 14 Loops: 50
Expected: 38 found 37
Sun Feb 01 14:04:09 EST 2009 Errors: 15 Loops: 51
Sun Feb 01 14:04:09 EST 2009 Errors: 15 Loops: 52
Sun Feb 01 14:04:09 EST 2009 Errors: 15 Loops: 53
Expected: 40 found 39
Sun Feb 01 14:04:13 EST 2009 Errors: 16 Loops: 54
Sun Feb 01 14:04:13 EST 2009 Errors: 16 Loops: 55
Sun Feb 01 14:04:13 EST 2009 Errors: 16 Loops: 56
Sun Feb 01 14:04:14 EST 2009 Errors: 16 Loops: 57
Sun Feb 01 14:04:14 EST 2009 Errors: 16 Loops: 58
Expected: 44 found 43
Sun Feb 01 14:04:17 EST 2009 Errors: 17 Loops: 59
Sun Feb 01 14:04:18 EST 2009 Errors: 17 Loops: 60
Expected: 45 found 44
Sun Feb 01 14:04:21 EST 2009 Errors: 18 Loops: 61
Sun Feb 01 14:04:21 EST 2009 Errors: 18 Loops: 62
Sun Feb 01 14:04:22 EST 2009 Errors: 18 Loops: 63
Sun Feb 01 14:04:22 EST 2009 Errors: 18 Loops: 64
Expected: 48 found 47
Sun Feb 01 14:04:25 EST 2009 Errors: 19 Loops: 65
Sun Feb 01 14:04:25 EST 2009 Errors: 19 Loops: 66
Sun Feb 01 14:04:26 EST 2009 Errors: 19 Loops: 67
Sun Feb 01 14:04:26 EST 2009 Errors: 19 Loops: 68
Expected: 51 found 50
Sun Feb 01 14:04:29 EST 2009 Errors: 20 Loops: 69
Sun Feb 01 14:04:30 EST 2009 Errors: 20 Loops: 70
Sun Feb 01 14:04:30 EST 2009 Errors: 20 Loops: 71
Sun Feb 01 14:04:31 EST 2009 Errors: 20 Loops: 72
Sun Feb 01 14:04:31 EST 2009 Errors: 20 Loops: 73
Sun Feb 01 14:04:31 EST 2009 Errors: 20 Loops: 74
Sun Feb 01 14:04:32 EST 2009 Errors: 20 Loops: 75
Sun Feb 01 14:04:32 EST 2009 Errors: 20 Loops: 76
Sun Feb 01 14:04:32 EST 2009 Errors: 20 Loops: 77
Sun Feb 01 14:04:33 EST 2009 Errors: 20 Loops: 78
Expected: 60 found 59
Sun Feb 01 14:04:36 EST 2009 Errors: 21 Loops: 79
Sun Feb 01 14:04:36 EST 2009 Errors: 21 Loops: 80
Sun Feb 01 14:04:37 EST 2009 Errors: 21 Loops: 81
Sun Feb 01 14:04:37 EST 2009 Errors: 21 Loops: 82
Sun Feb 01 14:04:38 EST 2009 Errors: 21 Loops: 83
Sun Feb 01 14:04:38 EST 2009 Errors: 21 Loops: 84
Expected: 65 found 64
Sun Feb 01 14:04:41 EST 2009 Errors: 22 Loops: 85
Sun Feb 01 14:04:42 EST 2009 Errors: 22 Loops: 86
Sun Feb 01 14:04:42 EST 2009 Errors: 22 Loops: 87
Expected: 67 found 66
Sun Feb 01 14:04:45 EST 2009 Errors: 23 Loops: 88
Sun Feb 01 14:04:45 EST 2009 Errors: 23 Loops: 89
Expected: 68 found 67
Sun Feb 01 14:04:49 EST 2009 Errors: 24 Loops: 90
Sun Feb 01 14:04:49 EST 2009 Errors: 24 Loops: 91
Sun Feb 01 14:04:49 EST 2009 Errors: 24 Loops: 92
Expected: 70 found 69
Sun Feb 01 14:04:52 EST 2009 Errors: 25 Loops: 93
Sun Feb 01 14:04:53 EST 2009 Errors: 25 Loops: 94
Expected: 71 found 70
Sun Feb 01 14:04:56 EST 2009 Errors: 26 Loops: 95
Sun Feb 01 14:04:57 EST 2009 Errors: 26 Loops: 96
Sun Feb 01 14:04:57 EST 2009 Errors: 26 Loops: 97
Expected: 73 found 72
Sun Feb 01 14:05:00 EST 2009 Errors: 27 Loops: 98
Sun Feb 01 14:05:00 EST 2009 Errors: 27 Loops: 99
Sun Feb 01 14:05:01 EST 2009 Errors: 27 Loops: 100
Errors: 27

Even after multiple executions, the errors are not occurring consecutively. If this would happen randomly, the chances of occurrence of at least two consecutive errors in 100, with 27% occurrence rate is quite high. It never happened, even after running multiple tests. The reason seams to be the 3 seconds delay of pooling  when reading a bad label value in case of an error. It seams ZK increases the probability of ignoring an event if this event comes right after another one. If the delay between clicks is increased (the red source code line), meaning the delay between requests is bigger, the error rate decreases, even reaches 0.

200 ms      50%

300 ms   27%

500 ms    0%

1000 ms  0%

I have always attempted to prevent usual web application users to submit a form twice (by disabling the submit button after the first submit) but my administrative interfaces model a complex data interaction, requiring a constant client-server interaction. The user is allowed to press a button more than once at very short intervals, for example by pressing the buttons “Up” or “Down” to specify the order of the elements in a list.

Another even simpler test is to send a given amount of clicks and then to evaluate how many clicks were accounted on the server side:

	public void testIncrement2() throws Exception {
		selenium.open("/testapp/test1.zul");

		for (int i = 0; i != 100; i++) {
			selenium.click("//td[text()='Increment']");
			Thread.sleep(350);
		}
		String s = selenium.getText("//span[@class='z-label']");
		int val = Integer.parseInt(s);
		System.out.println("Value: "+val+ " expected: 101");
	}

For a delay of 350 between requests, we receive an error rate of 49 clicks. For a delay of 100 milliseconds not less than 77 clicks fails to be recorded. The failure rate decreases as the request frequency decreases: for a delay of one second, the error rate is 0 and for 50 microseconds it is 81 percent!

In conclusion, I won’t recommend the usage of ZK in any application requiring a lot of client-server roundtrips. I have never tested their commercial version, they claim a substantial performance gain. I assume if the bug is still there, it only occurs less often.

“So what?” test for software

July 10, 2008

It is widely known that any published text must pass the “so what?” quality gate. The following post tries to extend this to software.

Imagine that you have a scripted language code (in my sample, apache maven) which allows the caller to provide values to one or more variables.

Within the pom.xml file, there is a line like:

<commandlineArgs>${data.directory}</commandlineArgs>

And the caller is able to provide a value to the variable, with the call

mvn install -Ddata.directory=/home/theuser

So far so good, but what about if the structure is much complicated, and the user misspells the variable name in the command line call? In this case, no error or warning is issued, the variable uses the default value. This only because the interpretor is unable to question “so what?” the command line.

The implementation of such a feature is difficult: the software should be able to keep track of the variables, their definition source and the amount of accesses. If an user defined variable had no accesses then is as good candidate for the “so what?”

Kubuntu 8.04 – two months later

July 6, 2008

Two months later after my first blog about Ubuntu, I am still using it.

My main use cases are office/browser/messenger (open office text, PDF view) and software development using Java (Eclipse, Netbeans). For software development reasons, I have few virtual machines within VMWare Server.

In two months I found lot of issues, some I managed to solve, some I can live with.

  • sometimes the system “freezes”. Any attempt to run sudo hangs. Reboot doesn’t work either. I have no idea why is this happening, although I suspect the network driver (Marvell Libertas / ndiswrapper).
  • sometimes the network connection drops and does not restore. It is again the network driver.
  • After a kernel or module update, the proprietary NVidia driver looses it’s settings. It seems the Package Manager of Ubuntu is unable to acknowledge that another X Server is installed.
  • Sometimes the available patches are out of sync, they cannot install. It seems in the same time are available conflicting versions of various packages.
  • I use KDE 4. The task bar becomes sometimes “fuzzy”. It fails to paint properly. The clock also shows unreadable digits.
  • ndiswrapper seems to be very sensitive: installing a Xen enabled kernel hangs the computer forever.

I think my problems will end when:

  • the wireless will be replaced by wired network (or I buy another wireless card, compatible with Linux)
  • Replacement of the video card. Two GeForce 9800 GX2 are on the way for a high performance computation project. At the end of the project I will use one of them as a graphic card, although this will require a power supply upgrade.

For these reasons, I strongly believe that Linux and particulary Ubuntu is not for the business users. Even if I am able to solve an issue, I will be unwilling and unable to solve it under pressure. More, the observed impact of the patches seems more aggresive than the impact of patches from the operating systems built in Redmond.

If you still plan to use Linux for business workstations (meaning – a large network of office computers, front line computers, etc), you may want to:

  • Use Linux certified hardware only (this will reduce the spectrum of choice and most of the certified hardware are more expensive than the average).
  • use a patch management tool to give you the ability to test the patches before sending it to your computers. Since most of the failures are hardware related, you should be able to test for all the hardware you own. Although such tools exist for Microsoft Windows, I have no idea who produces a patch management tool for Ubuntu.

[K]ubuntu 8.04

April 28, 2008

Last week I have installed Kubuntu 8.04 on my machine. And I have got a pleasant surprise. First time in my life, all hardware are functional after a Linux installation. My wireless card, Marvell Libertas based, required ndiswrapper, which was not on the installation CD (it’s supposed to download the driver of the network card), and I installed it manually with a memory stick.

Next, the nVidia Geforce 7 card (on the motherboard) required nVidia “proprietary” drivers. Since it works, I don’t see an issue with the lack of open source drivers.

The big surprise was the sound card, not recognized by other older distributions; no configuration was required and it “simply worked” after disabling the KDE sound manager.

Enabling Compiz under newly installed video driver was also easy and near the window effects I could find some useful shortcuts, such as full screen for any window. Also fonts are looking better rendered than with the standard VGA driver and the controls show more responsive.  Some other “Vista-like” candies like 3D window / desktop switching are also there.

No operating system is useful without applications. Kubuntu has two package managers, which seem very developer friendly. I could install Apache Maven, Sun Java SDK and Subversion and Eclipse with no effort, I have just queried the package database. This was _much_ easier than doing it under Windows, under normal circumstances.

So for a Java developer I think Linux is a better choice because of:

- zero cost of the operating system

- easy to install all the needed tools

- availability of major IDEs (Eclipse or Netbeans)

- availability of server applications (most if not all of the J2EE servers run on Linux as well)

- database servers available – Oracle, MySQL, Postgresql

Of course, there are also reasons to use Windows:

- Microsoft SQL Server, runs on Windows only

- .Net platform (this belongs actually to .net developers)

- you have hardware which does not works under Linux

So my conclusion are:

- installing Linux is faster then installing Windows

- installing Linux is more difficult than installing Windows, if you are unlucky with the hardware. If you are really unlucky with the hardware or simply not skilled enough, you may have no chance to make it run.

- installing developer tools is much easier and faster under Linux

GWT and J2EE

April 21, 2008

My quest after a consistent AJAX interface continues with the next stop, GWT. It sounds impressive that I only have to code Java, and the client will be compiled in static HTML and JavaScript by the GWT compiler. It provides the complete platform independence. Once compiled, the web pages can be used within any web server.

What about the client server communication? Is this a step back to the static content? Standard GWT provides mechanisms of calling a servlet, with  given classes, which have to implement a proprietary GWT serialization interface. Further researches revealed GWT-EXT, here are even MVC GUI controls available.

So once the client-server communication layer is implemented, development of enterprise J2EE applications can be accomplished quite fast. A closed source application, gwt-plus, with a cost of about $200/year provides a transparent way of working with the beans and collection of beans on the server side over the GWT RPC from the GWT client.

EJB3 Remote client: Hello world vs production usage

April 17, 2008

Yesterday I have made the first remote client for an Session bean. Hello world bean worked great, with a little research about how to configure the JNDI client to connect to the Glassfish server and what to provide in the CLASSPATH. I had to duplicate the remote interface and to delete the EJB annotation, since these JARs shouldn’t be imported on the client. I won’t do it in a production application, so I am ready for J2EE dependencies on the client as well.

The evil is as usual in detail. I don’t use EJB to write Hello word software. My session beans work with complex objects, persisted as entities. The beans do refer another beans, in one-to-many relations. In order to load such a list, the client needs to depend on the persistence library of the server, since that list is not a “vanilla” java.util.HashSet class, but one from TopLink or Hibernate, depending on the chosen EJB persistence.

So, near the entity beans, I had to import also the TopLink libraries in the client.

A solution to move from this dependency forest would be to employ web services. Regarding them, my experiences were not encouraging: they crash when receiving a reflexive reference (object A references object B and B references A) and they suffer performance issues both on server and client side when serving large collections.

Another ideas, is to use the value object pattern. This would mean at least duplication of my data model; but remember, I use MDA, so my model is generated from an UML model. Maybe the build of some plain objects could provide a special client JAR file (beans and service interfaces) and a copy mechanism from the beans, to be used on server side.


Follow

Get every new post delivered to your Inbox.