Web application frameworks in Java

When you know which type of web application you are to develop, it’s time to have a look at some possible choices.

I have tried to categorize some modern and popular web application frameworks in Java.

Simple server driven MVC page based

This category contains the traditional frameworks used for developing web applications with purely server driven application logic. They are based on complete HTML pages and uses the Model-View-Controller design pattern.

They do not directly support for client driven application logic, though it can be done if combined with a comprehensive JavaScript library like jQuery.

Full stack server driven MVC page based

This category contains some more advanced full stack frameworks. They are used for server driven application logic and not suitable for client driven application logic. They are inspired by Ruby on Rails.

Server driven component/widget based

Focus on UI components (widgets) instead of HTML pages, make development a bit more like desktop applications in frameworks like Swing. They are used for server driver application logic and not suitable for client driven application logic.

Client driven component/widget based

Useful for developing client driven application logic by automatically generating the client side JavaScript code.

  • Google Web Toolkit
  • Compiles Java to JavaScript and handle the cross-browser issues. Also abstracts away most of HTML. There is a good tutorial.

  • Vaadin
  • Based on GWT, but abstracts away even more HTML. Also handle the server side and automates AJAX based browser-server communication (using a native data format). A programming model which feels much more like Swing than usual web application development.

  • AribaWeb
  • Quite advanced full stack framework.

Posted in AJAX, Java, JavaEE, web | 2 Comments

Web applications and web frameworks

If you are to develop a web application, there are a lot if frameworks to choose between.

I assume that the web application by its nature needs to have bi-directional communication between the web browser and the server during the execution, initial downloading of resources is not enough. I also assume that the available technologies are HTML, CSS and JavaScript/AJAX; no Flash, Java applets, ActiveX, Silverlight or other browser plug-ins are used.

The first thing you should do is to decide what type of web application you want to develop, since that decision have a big impact on what frameworks that are suitable.

The primary question to ask is whether the application logic should be driven from the server or from JavaScript in the web browser. Before we had AJAX, server driven logic was the only possibility, but with AJAX it is also possible with client driven logic. It is also possible to have a mixture, but that should be avoided since it tends to make the application hard to test and lead to messy code design.

With server driven logic, most requests to the server return a complete HTML page. There may also be some AJAX requests which returns HTML fragments.

With client driven logic, only the initial request return a complete HTML page (usually a quite empty page). All subsequent requests are AJAX which return data from the server in JSON or XML format. This makes it possible to implement the server part as a web service which could be used for other things than providing data for the web application. This also makes the server part easy to test separately. (This is usually associated with Web 2.0.)

Secondly, the framework choice should also depend on whether you are developing the whole system from scratch, or if you have an existing backend with data persistence that you need a web user interface for. When developing from scratch, you can benefit from using a full stack framework with integrated data persistence, but with an existing backend you are probably better off with a framework which only does the web tier.

Posted in AJAX, web | 2 Comments

Mount your home directory with SSHFS in Linux

If you have your home directory on another machine, it’s common to use NFS to access it. NFS is easy to setup and works more or less out of the box on Linux. However, NFS is not secure and you need to have a carefully setup firewall in order to use it safely.

SSHFS is a more secure alternative, but it’s quite tricky to setup on the client side. It’s very easy to setup on the server though, you just need an SSH server with SFTP support.

This is the way to setup it on the client using Ubuntu desktop 10.04:

  1. First you have to get rid of the file .ICEauthority from your home directory. Create a .gnomerc file in your home directory:
    mkdir "/tmp/.ICE-${USER}"
    export ICEAUTHORITY="/tmp/.ICE-${USER}/.ICEauthority"
    
  2. Then you need to setup a local bootstrap home directory containing this .gnomerc file and your .ssh directory including your private key file. The remote home directory will be mounted over this. This can be on a read-only filesystem. You need to modify your .ssh/config file to explicitly point out your private key and known hosts files, add this:

    IdentityFile /home/username/.ssh/identity
    IdentityFile /home/username/.ssh/id_rsa
    IdentityFile /home/username/.ssh/id_dsa
    UserKnownHostsFile /home/username/.ssh/known_hosts
    
  3. Setup mounting on login by adding this to /etc/gdm/PostLogin/Default:

    sshfs -F ${HOME}/.ssh/config -o nonempty -o allow_other -o default_permissions ${USER}@theserver: ${HOME}
    
  4. Setup umounting on logout by adding this to /etc/gdm/PostSession/Default

    fusermount -u -z ${HOME}
    
Posted in Linux | 3 Comments

Using Vaadin with Maven

Vaadin is a comprehensive framework for developing web applications in Java. The Vaadin web site presents a number of ways to use Vaadin with Maven, but I am not completely satisfied with any of those. Here is how I do it.

Use a pom.xml like this:

<?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.thecompany</groupId>
	<artifactId>theapp</artifactId>
	<version>1.0</version>
	<packaging>war</packaging>
	<name>The App</name>

	<dependencies>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin</artifactId>
            <version>6.3.3</version>
        </dependency>
	</dependencies>

	<build>
		<plugins>
	        <plugin>
	            <groupId>org.apache.maven.plugins</groupId>
	            <artifactId>maven-war-plugin</artifactId>
	            <configuration>
	              <overlays>
	                <overlay>
		              <groupId>com.vaadin</groupId>
		              <artifactId>vaadin</artifactId>
		              <type>jar</type>
		              <includes>
		                <include>VAADIN/**</include>
		              </includes>
	                </overlay>
	              </overlays>
	            </configuration>
	         </plugin>

		<plugin>
			<groupId>org.mortbay.jetty</groupId>
			<artifactId>maven-jetty-plugin</artifactId>
			<version>6.1.17</version>
		</plugin>
        </plugins>
	</build>
</project>

And a src/main/webapp/WEB-INF/web.xml like this:

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

	<context-param>
	    <param-name>productionMode</param-name> <!-- Vaadin parameter -->
	    <param-value>true</param-value>
	</context-param>

	<servlet>
		<servlet-name>TheApp</servlet-name>
		<servlet-class>com.vaadin.terminal.gwt.server.ApplicationServlet</servlet-class>
		<init-param>
			<param-name>application</param-name>
			<param-value>com.thecompany.theapp.TheApp</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>TheApp</servlet-name>
		<url-pattern>/theapp/*</url-pattern>
	</servlet-mapping>
</web-app>

In this way, the VAADIN directory with themes and widgetsets from vaadin.jar will be automatically copied to the produced web-app where it can be served as static content for optimal performance. You can also put your own themes under src/main/webapp/VAADIN/themes and they will be merged with the default themes.

Build a .war file for your application using mvn package. You can also quickly test it using Jetty by running mvn jetty:run-exploded (jetty:run won’t work properly).

Posted in Java, web | 3 Comments

Implementing POX Web Services with Spring WS and JAXB

Spring Web Services together with JAXB 2.0 provides a convenient way to implement POX Web Services in Java.

POX means Plain Old XML, and a POX Web Service is a protocol based on sending XML over HTTP without using any well-known protocol framework like SOAP or XML-RPC.

First you have to define annotated JAXB classes for all XML request and response messages. If you have a schema, you can generate them with the xjc tool. Or you can create and annotate them manually. It can be a good idea to make one abstract base class for all requests, and one for all responses.

Then create a WEB-INF/spring-ws-servlet.xml file:

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

	<context:annotation-config />
	<context:component-scan base-package="com.acme.coolservice" />

        <oxm:jaxb2-marshaller id="marshaller" contextPath="com.acme.coolservice.jaxb" />
	<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping" />
	<bean id="messageFactory" class="org.springframework.ws.pox.dom.DomPoxMessageFactory" />
	<bean class="org.springframework.ws.server.endpoint.adapter.GenericMarshallingMethodEndpointAdapter">
	    <property name="marshaller" ref="marshaller" />
	    <property name="unmarshaller" ref="marshaller" />
	</bean>
</beans>

And finally implement your service endpoint class like this:

package com.acme.coolservice.pox;

import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;

import com.acme.coolservice.jaxb.*;

@Endpoint
public class CoolServiceEndpoint {

    @PayloadRoot(localPart="foo")
    public FooResponse foo(FooRequest request) {
        return new FooResponse();
    }

    @PayloadRoot(localPart="bar")
    public BarResponse bar(BarRequest request) {
        return new BarResponse();
    }

}

You can also make a client by adding this to your Spring context file:

    <oxm:jaxb2-marshaller id="marshaller" contextPath="com.acme.coolservice.jaxb" />
    <bean id="messageFactory" class="org.springframework.ws.pox.dom.DomPoxMessageFactory" />
    <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
        <property name="defaultUri" value="server-URI"/>
        <property name="marshaller" ref="marshaller"/>
        <property name="unmarshaller" ref="marshaller"/>
        <property name="messageFactory" ref="messageFactory"/>
    </bean>

And access it like this:

package com.acme.coolservice.client;

import com.acme.coolservice.jaxb.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ws.client.core.WebServiceTemplate;

public class CoolServiceClient {

    @Autowired
    private WebServiceTemplate webService;

    public void foo() {
        FooRequest request = new FooRequest();
        FooResponse response = (FooResponse)webService.marshalSendAndReceive(request);
    }

    public void bar() {
        BarRequest request = new BarRequest();
        BarResponse response = (BarResponse)webService.marshalSendAndReceive(request);
    }

}

The client uses the same JAXB classes as the server.

When running Java 6, or Java 5 inside a JavaEE 5 compliant application server, you already have the JAXB 2.x runtime available. If you run Java 5 without such application server, you have to include JAXB 2.x runtime libraries in your project.

You need these dependencies:

        <dependency>
            <groupId>org.springframework.ws</groupId>
            <artifactId>spring-ws-core</artifactId>
            <version>1.5.9</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.ws</groupId>
            <artifactId>spring-ws-core-tiger</artifactId>
            <version>1.5.9</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.ws</groupId>
            <artifactId>spring-oxm-tiger</artifactId>
            <version>1.5.9</version>
        </dependency>

You may have to make this exclusion from spring-ws-core when running in some application servers such as WebLogic:

            <exclusions>
		<exclusion>
			<groupId>wsdl4j</groupId>
    			<artifactId>wsdl4j</artifactId>
		</exclusion>
	    </exclusions>

Update:
Include this in WEB-INF/web.xml:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring-ws-servlet.xml</param-value>
</context-param>

<servlet>
    <servlet-name>context</servlet-name>
    <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet>
    <servlet-name>spring-ws</servlet-name>
    <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>spring-ws</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>
Posted in Java | 3 Comments

How to implement RESTful JSON Web Services in Java

You can implement RESTful Web Services in Java using the JAX-RS framework.

JAX-RS is part of the JavaEE 6 platform. But if you are not using a JavaEE 6 application server, you can use the reference implementation Jersey and embed it in any web application server.

However, it’s quite awkward to produce JSON output from Jersey.

Jersey has some support for producing JSON via JAXB, but to get the NATURAL encoding (which you probably want) you need JAXB 2.1. And that can be problematic since JAXB 2.0 is bundled with JavaSE 6 and with some application servers (such as WebLogic). Overriding that with a later version of JAXB can be really difficult. Using JAXB is also a bit clumsy if you only want to produce JSON.

And using the low-level JSON support in Jersey is not fun at all.

The solution is to use Jackson and refer to its JAX-RS integration package org.codehaus.jackson.jaxrs in Jerseys com.sun.jersey.config.property.packages parameter (remember to separate several packages with semicolon ; ).

Then just return POJO:s from your JAX-RS resource classes.

You need these dependencies:

	<dependency>
		<groupId>com.sun.jersey</groupId>
		<artifactId>jersey-core</artifactId>
		<version>1.1.4.1</version>
	</dependency>
	<dependency>
		<groupId>org.codehaus.jackson</groupId>
		<artifactId>jackson-core-asl</artifactId>
		<version>1.2.1</version>
	</dependency>
	<dependency>
		<groupId>org.codehaus.jackson</groupId>
		<artifactId>jackson-mapper-asl</artifactId>
		<version>1.2.1</version>
	</dependency>
	        <dependency>
	        <groupId>org.codehaus.jackson</groupId>
	        <artifactId>jackson-jaxrs</artifactId>
	        <version>1.2.1</version>
	</dependency>
Posted in AJAX, Java, JavaEE, web | 2 Comments

Linux with / mounted read-only 2.0

(This is a new version of a previous post updated to work with Ubuntu 9.10 (karmic).)

I wondered why you usually mount / (the root file system) read-write in Linux and decided to do some experiments to find out if it is possible to have it mounted read-only.

So why do you want to do that? Perhaps you have the root file system on a read-only media, such as CD-ROM. Or on a writable media which can only handle a limited number of writes, such as a CD-RW or flash disk. It would also increase security since it will be more difficult (though not impossible) for some malware to infect your system.

I found out that it is possible to mount / read-only, but only after some tweaking. Here is how I did it in Ubuntu 9.10 (karmic) desktop.

The first obvious step is to change the mount options to “ro” for / in /etc/fstab and reboot. But the tweaking has to be done first, so don’t reboot yet!

There are some locations in the file system which has to be writeable, the solution is to mount them as tmpfs. After some experiments, I found out that I had to mount the following locations as tmpfs (assuming that /dev is already mounted in an appropriate way):

  • /tmp
  • /media
  • /var/run
  • /var/lock
  • /var/tmp
  • /var/crash
  • /var/log
  • /var/lib/xkb
  • /var/lib/gdm
  • /var/lib/dhcp3 (only if you use DHCP client)
  • /var/lib/nfs (only if you use NFS)
  • /var/spool/cups

Ubuntu mounts /var/run and /var/lock as tmpfs by default. This is done by the mountall tool.

Add this to /etc/fstab:

none /tmp             tmpfs mode=1777,nodev,exec,nosuid 0 0
none /media           tmpfs mode=0755,nodev,noexec,nosuid 0 0
none /var/tmp         tmpfs mode=1777,nodev,noexec,nosuid 0 0
none /var/crash       tmpfs mode=0755,nodev,noexec,nosuid 0 0
none /var/spool/cups  tmpfs mode=0710,nodev,noexec,nosuid,gid=lp 0
none /var/log         tmpfs mode=0755,nodev,noexec,nosuid 0 0
none /var/lib/dhcp3   tmpfs mode=0755,nodev,noexec,nosuid 0 0
none /var/lib/xkb     tmpfs mode=0755,nodev,noexec,nosuid 0 0
none /var/lib/gdm     tmpfs mode=0775,nodev,noexec,nosuid,gid=gdm 0 0
none /var/lib/nfs     tmpfs mode=0755,nodev,noexec,nosuid 0 0

And add this to /etc/rc.local:

mkdir /var/log/apt

There are some files in /etc which have to be writeable:

  • /etc/mtab
  • /etc/resolv.conf (only if you use DHCP client and let it set DNS configuration)

I handle /etc/mtab by symlink it to /proc/mounts, that has some minor side-effects but I can live with it. I handle /etc/resolv.conf by symlinking it to /var/lib/dhcp3/resolv.conf. In order for this to work, you have to patch the DHCP client (dhcp3-client) accodring to this bug report (use the new version of the patch).

You also have to mount /home read-write somewhere, and I would not recommend using tmpfs. You can use a separate hard disk partition or NFS.

It is a bit tricky to get this to work with NFS. You have to set the NFS mount points in /etc/fstab as noauto and add these lines to /etc/init/statd.conf just before status portmap...

mkdir /var/lib/nfs/sm
mkdir /var/lib/nfs/sm.bak
mkdir /var/lib/nfs/rpc_pipefs

Then mount the NFS shares in /etc/gdm/PostLogin/Default. For some reason it did not work to do it from /etc/rc.local, perhaps due to delay in DHCP lookup.

Finally it might be a good idea to set a password for the root account, this enables you to switch to a virtual console (Ctrl-Alt-F1) and login as root if something goes wrong.

If you then do want to change anything, such as edit a file in /etc or install or upgrade a package, you can just remount / as read-write temporary (assuming that the media actually is writeable):
sudo mount -o rw,noatime,remount /

and revert to read-only when finished:
sudo mount -o ro,noatime,remount /

Note that this setup is for a desktop or laptop system, it’s probably not appropriate for a server.

If you have plenty of RAM (such as at least 1 GB), then you can also mount /var/cache/apt as tmpfs. That helps if you have limited free space on / and want to do a distribution upgrade.

Add this to /etc/fstab:

none /var/cache/apt   tmpfs mode=0755,nodev,noexec,nosuid 0 0

And add this to /etc/rc.local:

mkdir -p /var/cache/apt/archives/partial
Posted in Linux | 12 Comments

How to get microphone to work un Ubuntu 9.04

I finally got the microphone input on my Acer Veriton X270 to work un Ubuntu 9.04.

The trick is to uninstall PulseAudio and use ALSA only.

It even works in Skype.

Posted in hardware, Linux | 1 Comment

java.util.Map is broken in Java 5

Java 5 added generics. The collection classes was modified to make use generics to provide compile-time type-safe collections. Sadly, this was not done properly.

The worst problem is in the interface java.util.Map:

public interface Map<K,V> {
    // more methods...

    V get(Object key);
    V remove(Object key);
    boolean containsKey(Object key);
    boolean containsValue(Object key);
}

The key parameters to these methods ought to be declared to be K and not Object. Now we don’t get any type-safety for those methods. If you create a HashMap<String,String> and then by mistake try to use an int as key when looking up a value, you will not get any compile-time error. Worse yet, you will not even get any run-time error, it will just appear as if there is no value with that key (which in some sense is correct).

This can cause hard to find bugs like this:

public class MapTest {
    private Map<String,String> map = new HashMap<String,String>();

    public void setFoo(int i, String s) {
        map.put(String.valueOf(i), s);
    }

    public String getFoo(int i) {
        return map.get(i); // OOPS, should have been String.valueOf(i)
    }
}

(Yes, this code is pretty stupid, but it’s only a simple example.)

There are similar problems in java.util.Collection (contains and remove methods) and some other interfaces, but that’s less serious since they are not used very often. However, it’s very serious in java.util.Map since you always use the get method.

Posted in Java | 1 Comment

Misuse of HTTP GET is a cardinal sin

According to the RESTful style, you should make use of the four HTTP methods GET, POST, PUT and DELETE. However, in many cases only GET and POST is used, and POST is used when you really should use PUT or DELETE. I consider this as a quite minor issue.

However, using GET instead of POST (or PUT or DELETE) is much worse.

The current HTTP 1.1 specfication (RFC-2616) clearly states that a GET request must be safe, i.e. not have any significant side-effect on the server. So in order to change anything on the server, you must use POST (or PUT or DELETE). The older HTTP 1.0 specification (RFC-1945) from 1996 said the same.

This is important because the HTTP protocol supports caching, both in the client and in intermediate proxies. This caching may result in that GET requests will not get through to the server all the time. If you use GET to perform some action on the server, it will not work reliably unless you do ugly workarounds to circumvent the caching.

Public specifications of the HTTP protocol has made this clear for more than 12 years now. Misuse of the GET method in a web application, web service or any other application of HTTP is a cardinal sin.

Posted in web | 5 Comments