December 14, 2009

How to handle XML Schema Version?

Use the Schema verison attribute.
Pros:
  • Simple
Cons:
  • No XML Schema enforcement when stepping version and version number is concealed for user.
Recommendation:
  • Do no use.

Change the Schema location and keep the namespace.
Pros:
  • Good för maintaining backward compability. No depending XML files needs to be altered, simply upgrade implementing jar.
Cons:
  • Cannot tell from the XML file which implementing jar version is used.
Recommendation:
  • Use this technique to handle minor version upgrade.

Example:
http://camel.apache.org/schema/spring/camel-spring-1.6.X.xsd, in version 1.6.0-1.6.3 is the same targetNamespace used.

Change the Schema location and the namespace.
Pros:
  • Forces the user to upgrade the client code, when stepping version. Hard versioning control, no chanse to make misstake.
Cons:
  • No seamless upgrade. Upgrade will cost.
Recommendation:
  • Use this when stepping major version.

For you using JAXB, is it a good reminder that the namspace versionnumber is direclty reflected in the package name. So when uppgrading and if the depending generated code has changed namespace, i.e. package name will the depending code not compile. This can be a advantage since it will directly be apparent where in your code you have the dependencies.

XML Schema Design Pattern - Handling Versioning and Reuse

In my last project I have been working with service orientated integration and ESB, in such an architecture the domain model is represented with a canonical model of a XML schema. There several way you can design your schema which I will describe bellow, but what is more imported is the implication it has on:
  • Level of possibility to reuse your canonical model in different service.
  • Level of possibility to handle different version of same service.
  • Level of possibility to split your canonical data model into bit of pieces and process them in parallel.
Before laying out the different patterns I will explain different definition that I will use when evaluating the different patterns

Definition:
Root element – the first element a XML must contain. If a schema contains several root element it is possible to slice the XML document into several new XML document.

Global element – the elements that directly comes after the root element, possibly elements are 'element', 'complexType' and 'simpleType'.

Local element – nested element inside global element.

Russian Doll Example

Pros:
  • One root element, good for encapsulation.
  • All elements are local and encapsulated.
Cons:
  • No reuse of elements.
  • Easier to get started with.

Example Book-RussianDoll-v1.0.0.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     targetNamespace="http://ns.msc.se/examples/book-russiandoll/v1_0_0"
     xmlns:russ="http://ns.msc.se/examples/book-russiandoll/v1_0_0" 
     elementFormDefault="qualified">
 
 <xs:element name="book">
  <xs:complexType>
   <xs:sequence>
    <xs:element name="Title" type="xs:string" />
    <xs:choice>
     <xs:element name="AuthorList" minOccurs="0" maxOccurs="unbounded">
      <xs:complexType>
       <xs:sequence>
        <xs:element name="Author">
         <xs:complexType>
          <xs:sequence>
           <xs:element name="givenName" type="xs:string" />
          </xs:sequence>
         </xs:complexType> 
        </xs:element>
       </xs:sequence>
      </xs:complexType>
     </xs:element>
    </xs:choice>
   </xs:sequence>
  </xs:complexType>
 </xs:element> 
 
</xs:schema>

Salami Slide
Pros
  • Many root elements, the XML file can be sliced into numerous ways.
  • All elements are global, which allows reuse in other Schemas.

Cons
  • Does not encapsulate and hide the schema.
  • Usage of namespaces are almost a most, which makes usage more complex.

Example Book-SalamiSlice-v1.0.0.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     targetNamespace="http://ns.msc.se/examples/book-salamislice/v1_0_0"
     xmlns:salv1_0_0="http://ns.msc.se/examples/book-salamislice/v1_0_0" 
     elementFormDefault="qualified">

 <xs:element name="book">
  <xs:complexType>
   <xs:sequence>
    <xs:element ref="salv1_0_0:Title" />
    <xs:element ref="salv1_0_0:AuthorList" />
   </xs:sequence>
  </xs:complexType>
 </xs:element>

 <xs:element name="Title" type="xs:string" />

 <xs:element name="AuthorList">
  <xs:complexType>
   <xs:sequence>
    <xs:element ref="salv1_0_0:Author" minOccurs="0" maxOccurs="unbounded" />
   </xs:sequence>
  </xs:complexType>
 </xs:element>

 <xs:element name="Author">
  <xs:complexType>
   <xs:sequence>
    <xs:element ref="salv1_0_0:GivenName" />
    <xs:element ref="salv1_0_0:Surname" />
   </xs:sequence>
  </xs:complexType>
 </xs:element>
 
 <xs:element name="GivenName" type="xs:string" />
 
 <xs:element name="Surname" type="xs:string" />
 
</xs:schema>

When generating code via JAXB, wee can see that several classes are annotated with the @XmlRootElement. This says that we have several possible root element.

In the next example we show how to handle version and extending previous schema version.

Example Book-SalamiSlice-v1.0.1.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     targetNamespace="http://ns.msc.se/examples/book-salamislice/v1_0_1"
     xmlns:salv1_0_0="http://ns.msc.se/examples/book-salamislice/v1_0_0"
     xmlns:salv1_0_1="http://ns.msc.se/examples/book-salamislice/v1_0_1" 
     elementFormDefault="qualified">
 
 <xs:import namespace="http://ns.msc.se/examples/book-salamislice/v1_0_0" schemaLocation="Book-SalamiSlice-v1.0.0.xsd" />

 <xs:element name="book">
  <xs:complexType>
   <xs:sequence>
    <xs:element ref="salv1_0_1:Title" />
    <xs:element ref="salv1_0_1:Category" />
    <xs:element ref="salv1_0_0:AuthorList" />
   </xs:sequence>
  </xs:complexType>
 </xs:element>
 
 <xs:element name="Title">
  <xs:simpleType>
   <xs:restriction base="xs:string">
    <xs:minLength value="3" />
   </xs:restriction>
  </xs:simpleType>
 </xs:element>
 
 <xs:element name="Category" type="xs:string" />
 
</xs:schema>

Venetian Blind

Pros:
  • Only one root element, good for encapsulation.
  • All element are global, which allows reuse in other Schemas.
Cons:
  • Usage of namespaces are almost a most, which makes usage more complex.

Example Book-VenetianBlind-v1.0.0.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     targetNamespace="http://ns.msc.se/examples/book-venetianblind/v1_0_0"
     xmlns:ven="http://ns.msc.se/examples/book-venetianblind/v1_0_0" 
     elementFormDefault="qualified">

 <xs:element name="Book">
  <xs:complexType>
   <xs:sequence>
    <xs:element name="Title" type="ven:TitleType" />
    <xs:element name="AuthorList" type="ven:AuthorListType" />
   </xs:sequence>
  </xs:complexType>
 </xs:element>
 
 <xs:simpleType name="TitleType">
  <xs:restriction base="xs:string">
  </xs:restriction>
 </xs:simpleType>

 <xs:complexType name="AuthorListType">
  <xs:sequence>
   <xs:element name="Author" type="ven:AuthorType" minOccurs="0" maxOccurs="unbounded" />
  </xs:sequence>
 </xs:complexType>
 
 <xs:complexType name="AuthorType">
  <xs:sequence>
   <xs:element name="GivenName" type="ven:GivenNameType" />
   <xs:element name="Surname" type="ven:SurnameType" />
  </xs:sequence>
 </xs:complexType>
 
 <xs:simpleType name="GivenNameType">
  <xs:restriction base="xs:string">
  </xs:restriction>
 </xs:simpleType>

 <xs:simpleType name="SurnameType">
  <xs:restriction base="xs:string">
  </xs:restriction>
 </xs:simpleType>
 
</xs:schema>

Example Book-VenetianBlind-v1.0.1.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     targetNamespace="http://ns.msc.se/examples/book-venetianblind/v1_0_1"
     xmlns:ven1_0_0="http://ns.msc.se/examples/book-venetianblind/v1_0_0"
     xmlns:ven1_0_1="http://ns.msc.se/examples/book-venetianblind/v1_0_1" 
     elementFormDefault="qualified">

 <xs:import namespace="http://ns.msc.se/examples/book-venetianblind/v1_0_0" schemaLocation="Book-VenetianBlind-v1.0.0.xsd" />

 <xs:element name="Book">
  <xs:complexType>
   <xs:sequence>
    <xs:element name="Title" type="ven1_0_1:TitleType" nillable="true" />
    <xs:element name="Category" type="ven1_0_1:CategoryType" nillable="true" />
    <xs:element name="AuthorList" type="ven1_0_0:AuthorListType" />
   </xs:sequence>
  </xs:complexType>
 </xs:element>
 
 <xs:simpleType name="TitleType">
  <xs:restriction base="xs:string">
  </xs:restriction>
 </xs:simpleType>

 <xs:simpleType name="CategoryType">
  <xs:restriction base="xs:string">
   <xs:enumeration value="SPORT" />
   <xs:enumeration value="COOKING" />
   <xs:enumeration value="PROGRAMMING" />
  </xs:restriction>
 </xs:simpleType>
 
</xs:schema>

Conclusion
When starting of thinking of Schema one come to the conclusion that schema design is much like tradition OO design, where one must always consider if a properties and method should be hidden or exposed to other classes. The same yields for Schemas and in the real world one would scarcely use just one design pattern, but rather combine them.

November 2, 2009

Problem Running Eclipse in Ubuntu 9.10 Karmic Koala

After upgrading to Ubuntu 9.10, Eclipse started to behave strangely. Button seams to be non-responsive, so I googled for a solution and came up with this link.

http://www.norio.be/blog/2009/10/problems-eclipse-buttons-ubuntu-910

November 1, 2009

Writing to Syslog with Log4J and Testing It on Ubuntu 9.04 Jaunty

The preferred way to log in Linux is to write to the Syslog. For you that comes from the Windows world, Syslog is the equivalent for the Windows NT Event Log. Before you can ran the example below you need to enable Syslog Facility LOCAL1 on Ubuntu. The Facility can be looked as a filter and if you are running multiple programs on the same server, you might want to consider to let each program write to different Facility LOCAL[0-7].

To enable Facility LOCAL1 on Ubuntu 9.04 you first need to edit /etc/syslog.conf
>sudo gedit /etc/syslog.conf &

and add the following line
local1.*   /var/log/local1.log

But we are not done yet, since Log4J org.apache.log4j.net.SyslogAppender is using the underlying writer class org.apache.log4j.helpers.SyslogWriter that is using the java.net.DatagramPacket which is writing to the syslog remotely, we need to enable remote access to Syslog. We do that by changing:
>sudo gedit /etc/default/syslogd &

And changing the following:
SYSLOGD="-r"

Now we are done and we need to restarts the system log daemon, to make our changes take affect:
>sudo /etc/init.d/sysklogd restart

Finally we add the following configuration to our log4j.properties.
# configure the root logger
log4j.rootLogger=INFO, STDOUT, DAILY, SYSLOG_LOCAL1

# configure Syslog facility LOCAL1 appender
log4j.appender.SYSLOG_LOCAL1=org.apache.log4j.net.SyslogAppender
log4j.appender.SYSLOG_LOCAL1.threshold=WARN
log4j.appender.SYSLOG_LOCAL1.syslogHost=localhost
log4j.appender.SYSLOG_LOCAL1.facility=LOCAL1
log4j.appender.SYSLOG_LOCAL1.facilityPrinting=false
log4j.appender.SYSLOG_LOCAL1.layout=org.apache.log4j.PatternLayout
log4j.appender.SYSLOG_LOCAL1.layout.conversionPattern=[%p] %c:%L - %m%n

Maven2 Reference Literature

For some time the best book on Maven2 was “Better Builds with Maven” which can be downloaded from http://www.maestrodev.com/better-build-maven, but now there is finally a more updated book, “Maven: The Definitive Guide“. Which is available from

http://www.sonatype.com/books/maven-book/reference/public-book.html

The Promising Standardized JSR 303 Bean Validation and Example of Usage

For too long have the Java world lived without a standardized bean validation specification and soon will the final approval hopefully be approved (2 Nov 2009). What does this imply?
  1. Better Domain Driven Design, by putting the shallow domain validation in the POJO where it belongs.
  2. Hopefully we can finally get rid of Value Objects Pattern which is a dark heritage from the EJB 2.1 age and instead use domain POJO beans through out our architecture. There is of course exception to this rule, e.g. in service layer where the exposed model is totally different than the domain model or in a UI layer with heavy usage of line charts, there an OO model does not fit into a point orientation representation.
What is still to be proven is how the specification will fit into other framework, such as JPA, Apache Wicket or Spring Remoting. But one can rest ashore if one is using the standard validation model, the odds increase dramatically. And presumably will big framework such as Spring Framework and Apache Wicket adjust there framework to the standard.

Here follows a simple example of the usage of Bean Validation.

pom.xml
<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>se.msc.examples</groupId>
<artifactId>validation-domain</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>Validation :: Domain</name>
<url>http://www.msc.se/examples/validation</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<repositories>
<repository>
<id>repository.jboss.org</id>
<url>http://repository.jboss.org/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>

<dependencies>
<!-- common logging library -->
<!-- version is depended on hibernate-annotations v3.4.0.GA -->
<!--
http://repo1.maven.org/maven2/org/hibernate/hibernate-annotations/3.4.0.GA/hibernate-annotations-3.4.0.GA.pom
-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.4.2</version>
</dependency>
<!-- sun bean validation api -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
<!-- hibernate bean validation impl -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.0.0.GA</version>
</dependency>
<!-- test support -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<defaultGoal>install</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>

</project>

package se.msc.examples.validation.domain;

import java.io.Serializable;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private Long personId;
private String firstName;
@NotNull
@Size(min=1)
private String surname;
@NotNull
@Pattern(regexp=".+@.+\\.[a-z]+")
private String mail;

public Long getPersonId() {
return personId;
}

protected void setPersonId(Long personId) {
this.personId = personId;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getSurname() {
return surname;
}

public void setSurname(String surname) {
this.surname = surname;
}

public String getMail() {
return mail;
}

public void setMail(String mail) {
this.mail = mail;
}

}

package se.msc.examples.validation.domain;

import static org.junit.Assert.*;

import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class PersonTest {
private Validator validator;
private Person person;

@BeforeClass
public static void oneTimeSetUp() throws Exception {  
}

@AfterClass
public static void oneTimeTearDown() throws Exception {
}

@Before
public void setUp() throws Exception {
validator = Validation.buildDefaultValidatorFactory().getValidator();
person = new Person();
person.setFirstName("Magnus K");
person.setSurname("Karlsson");
person.setMail("magnus.k.karlsson@domain.se");  
}

@After
public void tearDown() throws Exception {
}

private  void debugPrint(Set> violations) {
for (ConstraintViolation violation : violations) {
String propertyPath = violation.getPropertyPath().toString();
String message = violation.getMessage();
System.out.println("invalid value for: '" + propertyPath + "': " + message);
}  
}

@Test
public void testValidate_OK() throws Exception {
Set> violations = validator.validate(person);
assertTrue(violations.size() == 0);
debugPrint(violations);
}

@Test
public void testValidate_FAIL_MAIL() throws Exception {
person.setMail("magnus.k.karlsson@domain");
Set> violations = validator.validate(person);
assertTrue(violations.size() == 1);
debugPrint(violations);
}

@Test
public void testValidate_FAIL_SURNAME() throws Exception {
person.setSurname(null);
Set> violations1 = validator.validate(person);
assertTrue(violations1.size() == 1);
debugPrint(violations1);

person.setSurname("");
Set> violations2 = validator.validate(person);
assertTrue(violations2.size() == 1);
debugPrint(violations2);  
}

}

The resource bundle message ValidationMessages.properties
javax.validation.constraints.Null.message=must be null
javax.validation.constraints.NotNull.message=must not be null
javax.validation.constraints.AssertTrue.message=must be true
javax.validation.constraints.AssertFalse.message=must be false
javax.validation.constraints.Min.message=must be greater than or equal to {value}
javax.validation.constraints.Max.message=must be less than or equal to {value}
javax.validation.constraints.Size.message=size must be between {min} and {max}
javax.validation.constraints.Digits.message=numeric value out of bounds (<{integer} digits>.<{fraction} digits> expected)
javax.validation.constraints.Past.message=must be a past date
javax.validation.constraints.Future.message=must be a future date
javax.validation.constraints.Pattern.message=must match the following regular expression: {regexp}


References:
JSR 303: Bean Validation
http://jcp.org/en/jsr/detail?id=303

Article comparing JSR 303 Reference Implementation And Spring 2.5 Validation
http://blog.jteam.nl/2009/08/04/bean-validation-integrating-jsr-303-with-spring/

JSR 303 Reference Material
http://people.redhat.com/~ebernard/validation/

JSR 303 Specification Leads Emmanuel Bernard Blog
http://in.relation.to/Bloggers/Emmanuel

Integrate JSR 303 Bean Validation And ApacheWicket

In my previous blog I was writing about the new promising standard JSR 303 Bean Validation. In this article I will write about JSR 303 Bean Validation and Apache Wicket. Let start with recapitulate the domain object Person and see how we used the Bean Validation annotation to annotate our property constraints.
package se.msc.examples.validation.domain;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

@Entity
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long personId;
@NotNull
@Size(min = 1, max = 250)
@Column(length = 250)
private String givenName;
@NotNull
@Size(min = 1)
@Column(length = 250)
private String surname;
@NotNull
@Pattern(regexp = ".+@.+\\.[a-z]+")
@Column(length = 250)
private String mail;

public Long getPersonId() {
return personId;
}

protected void setPersonId(Long personId) {
this.personId = personId;
}

public String getGivenName() {
return givenName;
}

public void setGivenName(String givenName) {
this.givenName = givenName;
}

public String getSurname() {
return surname;
}

public void setSurname(String surname) {
this.surname = surname;
}

public String getMail() {
return mail;
}

public void setMail(String mail) {
this.mail = mail;
}

}

This time I also have added sun's JPA annotation, because this is a domain object and sooner we want the domain objects to be persisted. We also the see that there is an overlap between the Bean Validation annotation and the JPA annotation. My approach to these is to use an open constraint approach for persistence and a narrowing/stricter definition with the Bean Validation for the domain layer. This way enables us to have a more flexible database, DBA would probably argue that this leads to bad data quality, but since we are building in validation directly in our domain object and writing small and easy to run unit test, to test these validation, there are no risk against bad data quality slipping through to the persistence layer. Actually we are protecting bad data to even reach the persistence layer long before, first in the presentation layer, but also we will use the same Bean Validation in the service layer. And all validation using the same code, the Bean Validation annotation, no more inventing the wheel over and over again in the different layers.

So how do we use the Bean Validation with the Apache Wicket? Well, there is no out-of-box integration, so I have written a few helper classes that will do that for us. These helper classes are actually worth using already how ever you will be using Bean Validation or not in your next project, because Apache Wicket is really to low-tech, like Swing, and when writing Apache Wicket classes from ground up requires you to write quite lengthy masses of code, this is not good. So lets start with our helper classes for writing org.apache.wicket.markup.html.form.Form.

package se.msc.examples;

import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.LoadableDetachableModel;

public class FormBuilder<T> extends Form<T> {
private static final long serialVersionUID = 1L;
public static final String SUBMIT = "submit";

public FormBuilder(final String id, final T modelObject) {
super(id, new CompoundPropertyModel<T>(new LoadableDetachableModel<T>(
modelObject) {
private static final long serialVersionUID = 1L;

protected T load() {
return modelObject;
}
}));
}

public void addTextField(final String propertyName) {
TextField<T> textField = new TextField<T>(propertyName);
textField.add(new BeanValidator<T>(getModelObject(), propertyName));
add(textField);
}

public void addSubmitButton(final FormButtonListener<T> listener) {
final FormBuilder<T> parent = this;
add(new Button(SUBMIT) {
private static final long serialVersionUID = 1L;

public void onSubmit() {
parent.execSubmit(listener);
}
});
}

public Form<T> create() {
return this;
}

public void execSubmit(final FormButtonListener<T> listener) {
listener.onSubmit(getModelObject());
}

}





package se.msc.examples;

import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;

import org.apache.log4j.Logger;
import org.apache.wicket.validation.INullAcceptingValidator;
import org.apache.wicket.validation.IValidatable;
import org.apache.wicket.validation.ValidationError;

public class BeanValidator<T> implements INullAcceptingValidator<T> {
private static final long serialVersionUID = 1L;
private static final Logger log = Logger.getLogger(BeanValidator.class);
private final Class<T> beanClass;
private final String propertyName;

@SuppressWarnings("unchecked")
public BeanValidator(final T beanObject, final String propertyName) {
this.beanClass = (Class<T>) beanObject.getClass();
this.propertyName = propertyName;
}

@Override
public void validate(IValidatable<T> validatable) {
log.info("validate... " + validatable.getValue());
ReflectionUtil<T> util = new ReflectionUtil<T>();
T beanObject = util.createInstance(beanClass);
util.setPropertyValue(beanObject, propertyName, validatable.getValue());
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<T>> violations = validator.validateProperty(beanObject, propertyName);
for (ConstraintViolation<T> violation : violations) {
String propertyPath = violation.getPropertyPath().toString();
String message = violation.getMessage();
log.error("invalid value for: '" + propertyPath + "': " + message);

ValidationError validationError = new ValidationError();
validationError.setMessage(message);
validatable.error(validationError);
}  
}

@Override
public String toString() {
return "[BeanValidator beanObject='" + beanClass + "']";
}

}


Lets now see how we use it in our Apache Wicket controller class.

package se.msc.examples;

import org.apache.log4j.Logger;
import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.panel.FeedbackPanel;

import se.msc.examples.validation.domain.Person;

public class PersonEditPage extends WebPage implements FormButtonListener<Person> {
private static final long serialVersionUID = 1L;
private static final Logger log = Logger.getLogger(PersonEditPage.class);
protected static final String FEEDBACK_PANEL = "feedbackPanel";
protected static final String PERSON_FORM = "personForm";
protected static final String GIVEN_NAME = "givenName";

public PersonEditPage(final PageParameters parameters) {
log.info("PersonPage...");
add(new FeedbackPanel(FEEDBACK_PANEL));
add(createForm(new Person()));
}

private Form<Person> createForm(Person person) {
FormBuilder<Person> builder = new FormBuilder<Person>(PERSON_FORM, person);
builder.addTextField(GIVEN_NAME);
builder.addSubmitButton(this);
return builder.create();
}

@Override
public void onSubmit(Person modelObject) {
log.info("onSubmit " + modelObject);
info("Successfully created '" + modelObject.getGivenName() + "'.");
}

}


And the accompanying html file

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd"
xml:lang="en" lang="en">
<head>
<title>Person Edit Page</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>

<div id="feedbackPanel" wicket:id="feedbackPanel">Feedback Panel</div>
<form id="personForm" wicket:id="personForm">
<fieldset style="width: 30em">
<legend>Person Edit</legend>
<table border="1" style="width: 100%">
<tr>
<td align="right">Given Name:</td>
<td><input id="givenName" wicket:id="givenName" type="text" style="width: 98%" /></td>
</tr>
<tr>
<td colspan="2" align="right">
<button id="submit" wicket:id="submit" type="submit">Submit</button>
</td>
</tr>
</table>
</fieldset>
</form>

</body>
</html>

Now lets write a simple test case to test our Apache Wicket validation.

package se.msc.examples;



import junit.framework.TestCase;



import org.apache.wicket.markup.html.form.Form;

import org.apache.wicket.markup.html.panel.FeedbackPanel;

import org.apache.wicket.util.tester.FormTester;

import org.apache.wicket.util.tester.WicketTester;



public class PersonEditPageTest extends TestCase {

private WicketTester tester;



@Override

public void setUp() throws Exception {

tester = new WicketTester(new WicketApplication());

tester.startPage(PersonEditPage.class);

tester.assertRenderedPage(PersonEditPage.class);

}



public void testLayout() throws Exception {

tester.assertComponent(PersonEditPage.FEEDBACK_PANEL,

FeedbackPanel.class);

tester.assertComponent(PersonEditPage.PERSON_FORM, Form.class);

}



public void testCreate_OK() throws Exception {

FormTester form = tester.newFormTester(PersonEditPage.PERSON_FORM);

form.setValue(PersonEditPage.GIVEN_NAME, "Magnus");

form.submit(FormBuilder.SUBMIT);



tester.assertRenderedPage(PersonEditPage.class);

tester.assertNoErrorMessage();

}



public void testCreate_GIVENNAME_FAIL() throws Exception {

FormTester form = tester.newFormTester(PersonEditPage.PERSON_FORM);

form.setValue(PersonEditPage.GIVEN_NAME, "");

form.submit(FormBuilder.SUBMIT);



tester.assertRenderedPage(PersonEditPage.class);

tester.assertErrorMessages(new String[] { "Field givenName is required." });



form = tester.newFormTester(PersonEditPage.PERSON_FORM);

form.setValue(PersonEditPage.GIVEN_NAME, " ");

form.submit(FormBuilder.SUBMIT);



tester.assertRenderedPage(PersonEditPage.class);

tester.assertErrorMessages(new String[] { "Field givenName is required." });  

}

}

October 19, 2009

How to Install Swedish Dictionary and Thesaurus for Open Office Writer

If you have installed a English distribution of Ubuntu you have already Open Office installed, but with no Swedish dictionary or Thesaurus. Do this to install:
  • Open Office Writer.
  • Select Tools->Language->More Dictionaries Online...
  • Download the two wanted files Dictionary and Thesaurus. Now you have to oxt-files on your computer.
  • Select Tools->Extension Manager and click Add then select oxt-file.
  • Restart Open Office and from Tools->Language->For All Text->More. In the window select installed language for selected document.

Clearlook Theme for Ubuntu – Clearlooks OSX

In the beginning I found it quite hard to find new themes, that was compatible with the standard Ubuntu way to install theme, i.e. from System->Preferences->Appearance.

But yesterday I found a nice OSX look that is not so grey as Mac OSX, it is also packaged in the standard Ubuntu installation way.

http://www.gnome-look.org/content/show.php/ClearlooksOSX?content=69487

How to Enable Code Completion and Syntax Control Against XML Schema with Eclipse

When I was writing Apache Camel configuration XML files, I was frustrated over that I had no code completion or XML syntax check against Apache Camel Schema, but of source is that doable in Eclipse. Simple download the Schema to your computer and then open Eclipe:
Window->Preferences->XML->XML Catalog
Click on Add and File System and select the downloaded Schema.
Now you can right-click in your XML file and select Validate.

September 29, 2009

Getting rid of notification “Network service discovery disabled” in Ubunut 9.04

After installing the latest Ubuntu I have haunted with the annoying notification “Network service discovery disabled. You current network has a .local domain, which is not recommended and incompatible with the Avahi network service discovery. The service has been disabled.”

First of all I have to google what Avahi is and found the following short summary here: https://help.ubuntu.com/community/HowToZeroconf

After that, I got rid of the notification message, by removing the below file and then starting the Avahi service, since some files where not properly auto-created during installation.
sudo rm /var/run/avahi-daemon/disabled-for-unicast-local
sudo /etc/ini.d/avahi-daemon start

After that I disabled the Avahi service, because I could not see any reason to autostart it when Ubuntu booted. You can disabled auto-services from System->Administration->Services. The last thing I did was to reboot and the problem was gone.

August 24, 2009

Firefox 3.5 brakes Eclipse 3.4

In mine previous blog I was writing about how to install Firefox 3.5 on Ubuntu 9.04, but that also had some unwanted side effect - it broke the Eclipse 3.4 installation!! Read more about http://hello-world-2-0.blogspot.com/2009/08/firefox-upgrade-broke-eclipse.html.

Configure Log4J DailyRollingFileAppender with custom PatternLayout

For some time I haven been planning to learn the mystic configuration of the org.apache.log4j.PatternLayout for Log4j and finally I have taken the time to do so.
  • c - The calling class name, if giving without precision is the fully qualified name returned.
  • C - The fully qualified class name.
  • d - The date of the logging request, can be formatted with java.text.SimpleDateFormat, i.e. %d{yyyy-MM-dd}
  • F - The name of the calling File.
  • l - The location information, same as %C%M(%F:%L). This can be slow.
  • L - The calling class line number
  • m - The logging message.
  • M - The calling class method.
  • n - The platform dependent line separator.
  • p - The logging Level.
  • r - The relative date in millisecond since application start.
  • t - The invoking thread.
  • [x|X] - the Message Diagnostic (MDC) information.

Now for some example. To be compliant with large open-source project such as Hibernate Annotation we use SLF4J as Logger interface. To use SLF4J, simply add the following to your Maven pom.xml
<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-log4j12</artifactId>

<version>1.4.2</version>

</dependency>

And if we run 'mvn dependency:tree', we see that the artifact also contains the log4j.jar implementation.
[INFO] Scanning for projects...

[INFO] Searching repository for plugin with prefix: 'dependency'.

[INFO] ------------------------------------------------------------------------

[INFO] Building Log4J Test

[INFO]    task-segment: [dependency:tree]

[INFO] ------------------------------------------------------------------------

[INFO] [dependency:tree]

[INFO] se.msc.development:log4j-test:jar:1.0-SNAPSHOT

[INFO] +- org.slf4j:slf4j-log4j12:jar:1.4.2:compile

[INFO] |  +- org.slf4j:slf4j-api:jar:1.4.2:compile

[INFO] |  \- log4j:log4j:jar:1.2.13:compile

[INFO] +- javax.mail:mail:jar:1.4.1:compile

[INFO] |  \- javax.activation:activation:jar:1.1.1:compile

[INFO] \- junit:junit:jar:4.5:test

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESSFUL

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 4 seconds

[INFO] Finished at: Mon Aug 24 03:05:27 CEST 2009

[INFO] Final Memory: 12M/144M

[INFO] ------------------------------------------------------------------------

And here follows an example of how to use SLF4J in your code.
package se.msc.log4j;

import org.junit.Test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Log4JTest {
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
private static final Logger log = LoggerFactory.getLogger(Log4JTest.class);

//import org.apache.log4j.Logger;
//private static final Logger log = Logger.getLogger(Log4JTest.class);

@Test
public void testFoo() throws Exception {
log.info("Info log message.");
log.error("Fatal log message.", new NullPointerException("Null pointer exceptopn."));
}

}

An the log4j configuration file log4j.properties
# configure the root logger
log4j.rootLogger=INFO, STDOUT, DAILY

# configure the console appender
log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
log4j.appender.STDOUT.Target=System.out
log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
log4j.appender.STDOUT.layout.conversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} [%p] %c:%L - %m%n

# configure the daily rolling file appender
log4j.appender.DAILY=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DAILY.File=/tmp/log4j/log4jtest.log
log4j.appender.DAILY.DatePattern='.'yyyy-MM-dd
log4j.appender.DAILY.layout=org.apache.log4j.PatternLayout
log4j.appender.DAILY.layout.conversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} [%p] %c:%L - %m%n

and when running the JUnit test:
2009-08-24 03:00:47.775 [INFO] se.msc.log4j.Log4JTest:18 - Info log message.
2009-08-24 03:00:47.783 [ERROR] se.msc.log4j.Log4JTest:19 - Fatal log message.
java.lang.NullPointerException: Null pointer exceptopn.
at se.msc.log4j.Log4JTest.testFoo(Log4JTest.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:73)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:46)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)

And now I final word about the DatePattern for the org.apache.log4j.DailyRollingFileAppender:
log4j.appender.DAILY.DatePattern='.'yyyy-MM-dd-a

Rolls over at midnight each day, as is the expected behaviour of a rolling log.

August 19, 2009

Bundle a Common Jar Into EJB Jar with Maven Plugin maven-ejb-plugin

Yesterday I had some problem with packing an EJB3 jar with Maven plugin maven-ejb-plugin. The problem seemed quite common. To bundle a common jar dependency into an EJB jar, but after reading the documentation for the maven-ejb-plugin at http://maven.apache.org/plugins/maven-ejb-plugin/, it seemed clear that the plugin lacked this capability. After several hour of failure I ran into a workaround . Instead of configure the maven-ejb-plugin I used the maven-dependency-plugin to copy the desired dependency jar into the target/classes directory and then configure maven-dependency-plugin to run before the package phase.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<configuration>
<generateClient>false</generateClient>
<ejbVersion>3.0</ejbVersion>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>process-classes</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>se.msc.development</includeGroupIds>
<includeArtifactIds>common</includeArtifactIds>
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>

And if you need to add the common.jar to the classpath in the MANIFEST file add the following configuration to maven-ejb-plugin.
<archive>
<manifest>
<addclasspath>true</addclasspath>
</manifest>
<manifestfile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestfile>
</archive>

August 11, 2009

Installing Firefox 3.5 on Ubunut 9.04 – the Jaunty Jackalope

After several crashes with Firefox 3.0x I decided to install the new Firefox 3.5, since the new version is managed with Synaptic Package Manager everything went smoothly, but with one gotcha. Do not remove the old Firefox, otherwise will panel shortcut and menu item be removed and when clicking on html files will nothing happens. Instead do the following:
sudo apt-get install firefox-3.5 firefox-3.5-gnome-support

Redirect the firefox link to the new version:
sudo rm /usr/bin/firefox
sudo ln -s /usr/bin/firefox-3.5 /usr/bin/firefox

July 29, 2009

Effective Unit Testing EJB 3.0 with OpenEJB

In my latest project we used EJB 3.0 and Maven2. And as any good programmer I wanted to have good code quality, which means good unit test test coverage, but my expectation on how to achieve this in an efficient manner was quite low, since mine previous experience with EJB 2.1 did not include any good testing experience. Even if coding EJB 3.0 has been greatly simplified, the fact still remains that the enterprise bean has still to be deployed before it can be tested. Of course can one program such that the logic is in a POJO rather directly in the bean itself, but to really be sure it is working the enterprise bean has to be deployed in a container, to be testable. So I started looking at different Maven plugin such as, jboss-maven-plugin and cargo-maven2-plugin, but then came across OpenEJB, which is really the salvation if you are developing EJB 3.0 and want good testing possibility. OpenEJB enable unit testing of enterprise beans as any POJO class! Lets look at some examples.
public class UserServiceSLSBTest {
private static final String EXPECTED_USERNAME_1 = "fornamn.1.efternamn@domain.com";
private static final String EXPECTED_USERNAME_2 = "fornamn.2.efternamn@domain.com";
private static final String EXPECTED_USERNAME_3 = "fornamn.3.efternamn@domain.com";
private Context ctx;

@BeforeClass
public static void oneTimeSetUp() {
}

@AfterClass
public static void oneTimeTearDown() {
}

@Before
public void setUp() throws Exception {
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.openejb.client.LocalInitialContextFactory");

props.put("blogUnmanaged", "new://Resource?type=DataSource");
props.put("blogUnmanaged.JtaManaged", "false");
props.put("blogUnmanaged.JdbcDriver", "com.mysql.jdbc.Driver");
props.put("blogUnmanaged.JdbcUrl", "jdbc:mysql://localhost:3306/blog");
props.put("blogUnmanaged.username", "root");
props.put("blogUnmanaged.password", "");
// TODO fix properties hibernate.hbm2ddl.auto=create-drop

ctx = new InitialContext(props);
}

@After
public void tearDown() {
}

private UserServiceLocal createUserService() throws Exception {
Object obj = ctx.lookup(UserServiceSLSB.class.getSimpleName() + "Local");

assertNotNull(obj);
assertTrue(obj instanceof UserServiceLocal);
return (UserServiceLocal) obj;
}

@Test
public void testCreateUser() throws Exception {
UserServiceLocal userService = createUserService();

User user = new User();
user.setUsername(EXPECTED_USERNAME_1);
user.setPassword(EXPECTED_USERNAME_1);
user.setRoles(Roles.ADMIN);

userService.storeUser(user);
}
}


And the Stateless Session Bean

@Stateless
public class UserServiceSLSB implements UserServiceLocal {
private static final Logger log = LoggerFactory.getLogger(UserServiceSLSB.class);
@PersistenceContext(name = "blog-ejb", unitName = "blog-ejb")
protected EntityManager em;
@Resource
private SessionContext context;

@Override
public User findUserByUsername(String username) {
log.info("findUserByUsername username='" + username + "'...");
Query q = em.createQuery("SELECT u from User as u where u.username=:username");
q.setParameter("username", username);
List list = q.getResultList();
return (list.size() > 0) ? (User) list.get(0) : null;
}

private void checkExistingUser(User user) throws DuplicateException {
User existingUser = findUserByUsername(user.getUsername());
if (existingUser != null)
throw new DuplicateException("Duplicate " + user);
}

@Override
public void storeUser(User user) throws CredentialException, DuplicateException {
log.info("storeUser " + user + "...");
checkExistingUser(user);
if (user.getUserId() == null)
em.persist(user);
else
em.merge(user);
}
}


And the SLSB local interface.

@Local
public interface UserServiceLocal {

public User findUserByUsername(String username);

public void storeUser(User user) throws CredentialException, DuplicateException;
}


And in the pom.xml simply add the dependency to OpenEJB and you are ready to go.

<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>openejb-core</artifactId>
<version>3.1.1</version>
<scope>test</scope>
</dependency>

Playing Commercial DVD with Ubuntu Jaunty Jackalope 9.04

I previously wrote a blog about how to play commercial DVD with Ubuntu Hardy Heron 8.10 Intrepid Ibex, but here comes an update how it is done with the latest Ubuntu.

sudo /usr/share/doc/libdvdread4/install-css.sh

July 22, 2009

Why Previous Java Web Framework Have Failed and Why Apache Wicket Will Succeed.

There exists numerous Java web framework (e.g. Struts, JSF, Spring MVC, etc.) and most of them are build upon the Model-View-Controller pattern, but though they have been used in numerous successful project, the Java community still produces new Java web framework. Why is that? According to me the previous Java web framework have several flaws:
  • The JSP technique is messy and clutters down the view page, maybe not for simple pages, but definitely for more complex pages.
  • The round trip when developing JSP pages is long since JSP pages can not be viewed, without first compiling them and running them in a web container. This severely slows down the project . This is especially true when one is fixing layout issues.
  • Web and JSP developer have different code base. This also slows down the project productivity, since when the web team ships new code or fixes, the JSP developer must copy past that into different JSP code.
  • Verbose XML configuration, is something the entire Java community is trying to get away from via Annotation and better default values. For example look at the EJB or Spring developing.
  • It is hard and verbose to unit test and even harder to maintain.
Though these many flaws there has not been any good alternative around to develop Java web solution, but now I would say the missing link is found – Apache Wicket.

The Apache Wicket architecture differs in two major way.
  • It does not use JSP technology for coding Views, instead it uses simple HTML and extend it with attributes.
  • You create components (TextField, CheckBox, etc.) in the Controller and add behavioral via Listener classes, such as in Swing.
These two major differences make a huge different:
  • Web and View developer use the same code base.
  • No need to compile and run the View in a container, simply open the View in a web browser and watch differences.
  • Easy to write unit test code.
Before going through an example, lets first take a brief overview over the main Wicket classes. Component are simple Java classes with supporting HTML markup.
Each Components holds a Model that is a simple Java class with data.

What is here imported is that the default Model are stateful and most example for Wicket uses the default model. This is unfortunate because that is not best practice, because stateful objects consume memory and make the application less scalable. The two most imported classes two use to make the application stateless is

IModel usersModel = new LoadableDetachableModel() {
protected Object load() {
return WicketApplication.get().getUserService().getUsers();
}
};

and

new BookmarkablePageLink(“newUser”, UserEditPage.class);

and if you need to pass data use Link with as little data as possible.

Link view = new Link("editUser", itemList.getModel()) {
public void onClick() {
setResponsePage(new UserEditPage(user.getUserId()));
}
};

Now look how easy and clean the unit test is:

public class UserEditPageTest extends TestCase {
protected static final Logger log = Logger.getLogger(UserEditPageTest.class);
private WicketTester tester;

public void setUp() {
tester = new WicketTester(new WicketApplication());
}

private void setUpNewUserEditPage() {
tester.startPage(UserEditPage.class);
tester.assertRenderedPage(UserEditPage.class);
}

public void testLayout() {
setUpNewUserEditPage();

tester.assertComponent(UserEditPage.FEEDBACK_PANEL, FeedbackPanel.class);
tester.assertComponent(UserEditPage.USER_FORM, Form.class);
}

public void testNewUser() {
setUpNewUserEditPage();

FormTester form = tester.newFormTester(UserEditPage.USER_FORM);
form.setValue(UserEditPage.USERNAME, "kalle.stropp@fake.com");
form.setValue(UserEditPage.PASSWORD, "validpassword");
form.select(UserEditPage.ROLES, 0);
form.submit(FormBuilder.BUTTON_SAVE);

tester.assertRenderedPage(UserListPage.class);
tester.assertNoErrorMessage();
}
}


And here follows the rest of the code:


public class UserEditPage extends TemplatePage implements ButtonListener, IChoiceRenderer {
private static final long serialVersionUID = 1L;
protected static final String FEEDBACK_PANEL = "feedbackPanel";
protected static final String USER_FORM = "userForm";
protected static final String USER_ID = "userId";
protected static final String USERNAME = "username";
protected static final String PASSWORD = "password";
protected static final String ROLES = "roles";
protected static final Logger log = Logger.getLogger(UserEditPage.class);

public UserEditPage() {
setModel(new CompoundPropertyModel(new LoadableDetachableModel() {
private static final long serialVersionUID = 1L;

protected Object load() {
return new User();
}
}));
init(false);
}

public UserEditPage(final long userId) {
setModel(new CompoundPropertyModel(new LoadableDetachableModel() {
private static final long serialVersionUID = 1L;

protected Object load() {
User user = WicketApplication.get().getUserService().loadUser(userId);
user.setPassword(null); // hide current password
return user;
}
}));
init(true);
}

protected String getPageTitle() {
return "userEditPage.title";
}

public void init(boolean readOnly) {
add(new FeedbackPanel(FEEDBACK_PANEL));
add(createForm(readOnly));
}

public Form createForm(boolean readOnly) {
FormBuilder builder = new FormBuilder(USER_FORM, getModel());
builder.addLabel(USER_ID);
builder.addTextField(USERNAME, true, 30, readOnly);
builder.addPasswordTextField(PASSWORD);
User user = (User) builder.getModelObject();
builder.addDropDownChoice(ROLES, Arrays.asList(user.getRoles().getValues()), this);
builder.addSubmitButton(this);
return builder.create();
}

@Override
public void onSubmit(Object modelObject) {
log.info("onSubmit " + modelObject);
WicketApplication.get().getUserService().storeUser((User) modelObject);
setResponsePage(UserListPage.class);
}

@Override
public Object getDisplayValue(Object object) {
return ((Roles) object).getRole();
}

@Override
public String getIdValue(Object object, int index) {
return ((Roles) object).getRole();
}
}


And the HTML


<html >
<head > </head >
<body >

<wicket:extend >

<div wicket:id="feedbackPanel" >Feedback Panel </div >

<form wicket:id="userForm" >
<fieldset style="width:250px;" >
<legend > <wicket:message key="userEditPage.userForm" >User Form </wicket:message > </legend >
<table >
<tr >
<td align="right" > <wicket:message key="userEditPage.userId" >UserId </wicket:message >: </td >
<td > <span wicket:id="userId" id="userId" >1 </span > </td >
</tr >
<tr >
<td align="right" > <wicket:message key="userEditPage.username" > <u >U </u >sername </wicket:message >: </td >
<td > <input wicket:id="username" type="text" name="username" accesskey="u" / > </td >
</tr >
<tr >
<td align="right" > <wicket:message key="userEditPage.newPassword" >New <u >p </u >assword </wicket:message >: </td >
<td > <input wicket:id="password" type="password" name="password" accesskey="p" / > </td >
</tr >
<tr >
<td align="right" > <wicket:message key="userEditPage.roles" > <u >R </u >oles </wicket:message >: </td >
<td > <select wicket:id="roles" > </select > </td >
</tr >
<tr >
<td colspan="2" align="right" >
<button wicket:id="save" type="submit" accesskey="s" > <wicket:message key="userEditPage.save" > <u >S </u >ave </wicket:message > </button >
</td >
</tr >
</table >
</fieldset >
</form >

</wicket:extend >

</body >
</html >

July 5, 2009

Good Java Open-Source Summary Site

Sometimes you come across good sites that you want to share with others. And today it happened I came across a good site that summaries a lot of Java open-source project. Which is a good starting page if you are looking for new Java library, for your new Java project. Enjoy!

http://java-source.net/

May 6, 2009

Thunderbird Lightning 0.9 on Ubuntu 9.04 (Jaunty Jackalope)

Yesterday I upgraded to Ubuntu 9.04, every thing went smoothly as always with Ubuntu. The day before I did a new installation of Windows XP and what a pain it was! I have to manually install literally every drivers – chipset, graphic, network, etc. And after every install you did have to restart. But when installing Ubuntu everything just works, but when doing the upgrade I did discover one thing. You should not install Lightning 0.9 by downloading the xpi-file and from Thunderbird install the add-ons, but instead use synaptic.

sudo apt-get install lightning-extension
And if you are still using Ubuntu 8.1 you should install libstdc++5

sudo apt-get install libstdc++5

For more details of the bug read:

https://bugs.launchpad.net/ubuntu/+source/thunderbird/+bug/278853

April 15, 2009

Frukostseminarium Integrationsresa från lättviktigt ramverk till fullskalig standardiserad Enterprise Service Bus (ESB)

Den 29 april kommer jag att hålla frukostseminarium om Apache Camel, Enterprise Integration Pattern och Apache ServiceMix på MSC kontor. Seminariumet är riktat till utvecklare och projektledare och kommer innehålla rikligt med demos, så om du är intresserad att lära dig mera om de olika integrationslösningar, anmäl dig då till magnus.k.karlsson@msc.se.

Mer information finns på http://www.msc.se/tjanster/utbud-it-seminarier/it-konsulter-Integrationsresa_fran_lattviktigt-ramverk_till_fullskalig_standardiserad_Enterprise_Service_Bus_ESB.html.

March 6, 2009

SOA by Examples

SOA is a buzz word that have been round for some time, but when you search for information about SOA it is hard to find hands on information what SOA really is and also examples of SOA. The lack of concrete example is a problem for us practical people which tend to learn new thing by examples and not read abstract theories about new technology. We do that but not before we got a god grasp of what we are learning. It is with that background I decided to write this blog.

Before going through examples, let us look what does SOA promises us, i.e. the goals of SOA:
The reuse of existing system, when building new application.

So how do we do that?
Encapsulate existing system with a fronting API and build the rest of the functionality as reusable services/components.

Enough with theory, now lets take some examples.

In this example the business case is to create a new application that can place customer orders, but with the criteria to reuse existing back-end solutions.

The SOA solution is built of the following reusable block
  • Basic Data Service - CRUD operations.
  • Composed Services - business logic.
  • Process Services – complex business logic.
Another example is a unified patience journal system.
An additional example could be Package Tour Operation containing the following services:
  • Flight Booking
  • Hotel Booking
  • Car Rental
  • Event Booking.
What is imported when talking about SOA is not to get stuck which techniques to use, but to focus on which service to use and what to fill them with, so they are reusable.

February 28, 2009

Enterprise Integration Diagram for Apache ServiceMix, Camel and Petal

One of the challenge when doing integration job with an ESB solution is to visualize it. If you are using Eclipse rescue is on the way - Eclipse Enterprise Integration Designer, STP.

The Eclipse STP project implement, some of the most imported pattern of the Enterprise Integration Pattern.

The project is still in incubation and there are some problem to run it, even if you follow the installation instruction from the STP site.

Installation
  • Download Eclipse Ganymede SR1 Enterprise edition.
  • Start Eclipse and open Help → Software Updates...
  • Select Ganymede → SOA → STP Designer, see snapshot. and install.
  • After restart, close Eclipse and download patch from http://webui.sourcelabs.com/eclipse/issues/240077
  • Extract the zip file to eclipse/plugins folder and start Eclipse.

Creating Integration Patterns Diagram
  • Create a pattern project, e.g. a simple Java project.
  • Create New and Other and select Integration Patterns Diagram.
  • At the time being is unfortunately only ServiceMix and Petal, supported, so select ServiceMix.
  • End the guide and finish.

After that you are set to create diagrams.



February 27, 2009

Clustering and CAP Theorem

When designing an application for clustering one should first be aware of the CAP (Consistency, Availability and Partitioning) theorem. The theorem states that you can only have two of the three CAP properties at the same time.

The Consistency means that all users see the same set of data, even when data updated or deleted. This is normally achieved with storing data to a database and using transactions.

Availability is achieved through replicating data, so that data is always available even in case of failure.

The last, Partitioning, means that the system is partitioning tolerant, i.e. the system holds when it is distributed over several servers and machines.

So which one should go? Well when building highly loaded applications as Google or Amazon the natural answer is Consistency, because letting the system not be available during failure or being not responsive during high load is not a options. This is quite interesting because most programmers are raised with the idea of using a database as a foundation for an application. And this idea must now go. Or? Well it is not so black and white.

The main key of building clustered application is twofold:
  • Asynchronous communication. E.g. Amazon has a separate service displaying what books other people has also bought. Failure of this service should not hinder the rest of the page to be rendered.
  • Brake down your application and analyze each part individually according to CAP properties. Does payment must be consistent? Probably. Does user information needs to be consistent. Probably not. Etc.
After you analyzed your application into different clustering functions you keep these data separated, because they will be deployed differently and independently.

So to achieve an High Availability and Partitioned Tolerant application is through scaling out, I.e. using more machines and using:
  • Stateless data, i.e. the applications server only holds request data.
  • Replicate read intensive data through a master/slave setup.
  • Caching data.
  • Sharding database, i.e. using multiple databases and manually decide which tables goes into which database.

February 22, 2009

Hibernate Search Example

In my previous blog I was writing about Hibernate Search in general, but in this blog I will show you code examples of using Hibernate Search.

The preferred and easiest way to get started is to use Maven2, if you are not able to use Maven2 then please download the relevant jar file.

<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>se.msc</groupId>
<artifactId>hibernatesearch</artifactId>
<version>0.0.1-SNAPSHOT</version>
<repositories>
<repository>
<id>repository.jboss.org</id>
<name>JBoss Maven Repository</name>
<url>http://repository.jboss.org/maven2</url>
<layout>default</layout>
</repository>
</repositories>
<dependencies>
<!-- For Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.5</version>
<scope>test</scope>
</dependency>
<!-- Hibernate Core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.3.1.GA</version>
</dependency>
<!-- Hibernate Annotation -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.4.0.GA</version>
</dependency>
<!-- Hibernate Annotation uses SLF4J -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.2</version>
</dependency>
<!-- Hibernate EntityManager -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.4.0.GA</version>
</dependency>
<!-- Hibernate Validator
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>3.0.0.ga</version>
</dependency> -->
<!-- Hibernate Search -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search</artifactId>
<version>3.1.0.GA</version>
</dependency>
<!-- Hibernate Search 3part Lib -->
<!-- Solr's Analyzer Framework -->
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-common</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-core</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-snowball</artifactId>
<version>2.4.0</version>
</dependency>
<!-- MySQL JDBC connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
In this example I will be using Hibernate Core, Hibernate Annotation and Hibernate Search. I will not use Hibernate EntityManager, but using EntityManager instead of Session is and easy thing to do and will not impact the concept or code significantly.

Lets start with configure our Hibernate Core with hibernate.cfg.xml.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">
jdbc:mysql://localhost:3306/test?createDatabaseIfNotExist=true&amp;useUnicode=true&amp;characterEncoding=utf-8
</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.hbm2ddl.auto">create-drop</property> <!-- update -->

<!-- Hibernate Search -->
<!-- org.hibernate.search.store.FSDirectoryProvider -->
<!-- org.hibernate.search.store.RAMDirectoryProvider for test -->
<property name="hibernate.search.default.directory_provider">
org.hibernate.search.store.RAMDirectoryProvider
</property>
<property name="hibernate.search.default.indexBase">
/home/magnus/tmp/lucene/indexes
</property>

<!-- Mapped classes -->
<mapping class="se.msc.hibernatesearch.domain.Person" />
</session-factory>
</hibernate-configuration>
The Hibernate Search comes with sensible default values and there is actually only two values that needs configuring the directory provider and the base directory of the index files.

In this example I will be using JUnit as start class and since unit tested class are run over and over again I will for consistency use an in-memory index in combination with drop and create the database schema. This way I will always get a clean start whenever restarting the JUnit text.

To make our example complete here is the log4j.properties file.

# Root logger option
log4j.rootLogger=INFO, stdout

# Log native SQL
log4j.logger.org.hibernate.SQL=debug
log4j.logger.org.hibernate.bind=debug

# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
To be able to use Hibernate from JUnit we need the popular a HibernateUtil.

public class HibernateUtil {

private static final SessionFactory sessionFactory;

static {
try {
AnnotationConfiguration conf = new AnnotationConfiguration();
sessionFactory = conf.configure().buildSessionFactory();
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}

public static Session getSession() throws HibernateException {
return sessionFactory.openSession();
}
}
Now lets start with annotating our domain class. For simplicity I will only use one class here.

@Entity
@Table(name = "PERSON")
@Indexed
public class Person implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@Column(name = "PERSON_ID", updatable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
@DocumentId
private Long id = null;

@Column(name = "FIRSTNAME", nullable = false, length = 250)
@Field(index = Index.TOKENIZED, store = Store.YES)
private String firstname = "";

@Column(name = "BIRTHDATE", nullable = false)
@Field(index = Index.UN_TOKENIZED, store = Store.YES)
@DateBridge(resolution = Resolution.DAY)
private Date birthdate = new Date();

public Person() {
}

public Person(String firstname, String birthdate)
throws IllegalArgumentException {
setFirstnameFromInput(firstname);
setBirthdateFromInput(birthdate);
}

public Long getId() {
return id;
}

protected void setId(Long id) {
this.id = id;
}

public String getFirstname() {
return firstname;
}

public void setFirstname(String firstname) {
this.firstname = StringUtil.setEmptyStringAsNull(firstname);
}

public void setFirstnameFromInput(String firstname) {
this.firstname = StringUtil.setEmptyStringAsNullAndTrim(firstname);
}

public Date getBirthdate() {
return birthdate;
}

public void setBirthdate(Date birthdate) {
this.birthdate = DateUtil.setTodayAsNull(birthdate);
}

public void setBirthdateFromInput(String birthdate)
throws IllegalArgumentException {
this.birthdate = DateUtil.setTodayAsNullAndParse(birthdate);
}

public String toString() {
return "Person {" + "id=" + id + ", firstname='" + firstname
+ "', birthdate='" + DateUtil.format(birthdate) + "'}";
}
}
There is not much to it. We use @Indexed to mark the class searchable, @DocumentId for primary key, @Field for simple properties and @DateBride for properties that need transformation, remember that Lucene only works with strings.

All Hibernate Search annotation are documented in org.hibernate.search.annotations

There is only two annotation that need further explanation:

index (Index.TOKENIZED | Index.UN_TOKENIZED)
Tokenized split the text into words (Tokens) and removes insignificant words. See example.


Untokenized leaves the text unchanged.

store (Store.YES | Store.NO)
Both options indexed the field, but Store.YES writes the field to Lucene index file and makes it available via Luke. But the main difference is that now one can utilize projection which means you can avoid even touching the database, that is the benefit we are looking for when writing high speed search application. The main drawback when using project is that raw Object, containing String value, are returned, instead of domain object graphs.

Using Store.YES should be the preferred way whenever you want high performance, and if you need to further manipulate the object, simple do a database round trip and grab the persisted domain object via the primary key.

Another drawback of projection is that you can only index simple properties and on-to-one (embedded) object, but not other many relations. This is due of difference in the object mode between Lucene and Hibernate.

public class HibernateTemplate {

public Object execute(HibernateCallback action) throws HibernateException {
Session session = null;
Transaction tx = null;
Object object = null;
try {
session = HibernateUtil.getSession();
tx = session.getTransaction();
tx.begin();
object = action.execute(session);
tx.commit();
} catch (HibernateException e) {
if (tx != null && tx.isActive())
tx.rollback();
throw e;
} finally {
if (session != null)
session.close();
}
return object;
}

public void saveOrUpdate(final Object entity) throws HibernateException {
execute(new HibernateCallback() {

@Override
public Object execute(Session session) throws HibernateException {
session.saveOrUpdate(entity);
return null;
}
});
}

public List find(final String query) throws HibernateException {
return (List) execute(new HibernateCallback() {

@Override
public Object execute(Session session) throws HibernateException {
return session.createQuery(query).list();
}
});
}

public List findWithFullText(String query, String field,
final Class entity) throws HibernateException, ParseException {

QueryParser parser = new QueryParser(field, new StandardAnalyzer());
final org.apache.lucene.search.Query lucQuery = parser.parse(query);

return (List) execute(new HibernateCallback() {

@Override
public Object execute(Session session) throws HibernateException {
FullTextSession ftSess = Search.getFullTextSession(session);
return ftSess.createFullTextQuery(lucQuery, entity).list();
}
});

}

public List findWithFullTextAndProjection(String query, String field,
final Class entity) throws HibernateException, ParseException {

QueryParser parser = new QueryParser(field, new StandardAnalyzer());
final org.apache.lucene.search.Query lucQuery = parser.parse(query);

return (List) execute(new HibernateCallback() {

@Override
public Object execute(Session session) throws HibernateException {
FullTextSession fTS = Search.getFullTextSession(session);
FullTextQuery fTQ = fTS.createFullTextQuery(lucQuery, entity);
fTQ.setProjection("id", "firstname", "birthdate");
return fTQ.list();
}
});

}
}

public interface HibernateCallback {

public Object execute(Session session) throws HibernateException;
}

public class SessionTest {

private static final Person[] INIT_DATA = new Person[] {
new Person("Magnus", "1974-01-01"),
new Person("Bertil", "1973-02-02"),
new Person("Klara", "1972-03-03") };

private static final String FIELD = "firstname";

private static final Class ENTITY = Person.class;

HibernateTemplate temp = new HibernateTemplate();

private void printPersonResult(Person[] persons) {
System.out.println("Number of hits: " + persons.length);
for (Person person : persons) {
System.out.println(person);
}
}

private void printObjectResult(List res) {
System.out.println("Number of hits: " + res.size());
for (Object row : res) {
Object[] objects = (Object[]) row;
for (Object o : objects)
System.out.println(o);
}
}

@Test
public void testSaveAll() throws Exception {
for (Person person : INIT_DATA)
temp.saveOrUpdate(person);
}

@Test
public void testFindAll() throws Exception {
List res = temp.find("from Person");
Assert.assertEquals("Testing find all.", 3, res.size());
printPersonResult(res.toArray(new Person[0]));
}

@Test
public void testFullText() throws Exception {
String query = "firstname:Magnus";
List res = temp.findWithFullText(query, FIELD, ENTITY);
Assert.assertEquals("Testing firstname search.", 1, res.size());
printPersonResult(res.toArray(new Person[0]));
}

@Test
public void testFullText2() throws Exception {
String query = "birthdate:19720303";
List res = temp.findWithFullText(query, FIELD, ENTITY);
Assert.assertEquals("Testing birthdate search.", 1, res.size());
printPersonResult(res.toArray(new Person[0]));
}

@Test
public void testFullTextProjection() throws Exception {
String query = "firstname:Magnus OR birthdate:19730202";
List res = temp.findWithFullTextAndProjection(query, FIELD, ENTITY);
Assert.assertEquals("Testing search projection.", 2, res.size());
printObjectResult(res);
}
}