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 <T> void debugPrint(Set<ConstraintViolation<T>> violations) {
    for (ConstraintViolation<T> 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<ConstraintViolation<Person>> 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<ConstraintViolation<Person>> violations = validator.validate(person);
    assertTrue(violations.size() == 1);
    debugPrint(violations);
  }

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

    person.setSurname("");
    Set<ConstraintViolation<Person>> 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." });  
  }

}