Posts Tagged ‘Java’

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.

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?”

[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