Thursday, December 31, 2009

Bookmark and Share

Jetty is widely appreciated as low-footprint and lightning-fast web container. That makes it also a perfect fit to be used as development runtime, where short turnaround times are an absolut must.

I used to work with the Jetty Maven plugin, which supports hot-deploying applications after any code changes while Jetty is running. This works pretty well, but comes at the cost that your session data is lost during re-deployment and depending on your application's complexity it also can take some seconds to get it up running again.

So I tried another option: running Jetty in embedded mode. For that purpose Jetty provides a comprehensive API, which we can use to write a simple main class that starts up a Jetty instance serving the application we are currently developing:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class JettyRunner {

    public static void main(String[] args) throws Exception {

        Server server = new Server();

        Connector connector = new SelectChannelConnector();
        connector.setPort(8080);
        connector.setHost("127.0.0.1");
        server.addConnector(connector);

        WebAppContext wac = new WebAppContext();
        wac.setContextPath("/myapp");
        wac.setBaseResource(
            new ResourceCollection(
                new String[] {"./src/main/webapp"}));

        server.setHandler(wac);
        server.setStopAtShutdown(true);
        server.start();
        server.join();
    }
}

The code is pretty much straight forward: first a connector with port and hostname is configured, then a context for the application is created and registered with the server, which finally is started up.

When we launch this class in debugging mode from within our IDE, code changes are immediately applied to the running application without the need to re-deploy or restart it due to Java's hot code replacement mechanism.

Furthermore all changes to the files under "src/main/webapp" are instantly visible, as the files are served directly from there.

The reduced number of required restarts/redeployments greatly improves development productivity. Basically restarting is only required when modifying deployment descriptors (such as web.xml) or when class signatures are modified (e.g. by adding new methods).

Running JSF applications

This works like a charm for basic servlets, but things are getting a bit more complicated, when JSF comes into play.

The reason is that JSF searches for all classes carrying any of the JSF annotations (such as @ManagedBean) when starting up. This scan takes place in the directory "META-INF/classes". As this folder doesn't exist in our case, no single managed bean will be detected.

How can this problem be solved? First of all the output folder of the application must be added to the WebAppContext's resource collection. In case of a Maven-based project we have to add the "target" directory:

1
2
3
4
5
...
wac.setBaseResource(
    new ResourceCollection(
        new String[] { "./src/main/webapp", "./target" }));
...

But the problem remains that JSF searches class files in "WEB-INF/classes", although in our case they are located under "classes".

We could modify the destination of class files (by setting Maven's property ${project.build.outputDirectory}, but I wouldn't really recommend this. Diverging from Maven's conventions makes your project harder to understand for other developers and as rumors go there still are Maven plugins around that directly access "target/classes" instead of referencing said property.

Resource aliases

I studied Jetty's API for a while and came across the concept of resource aliases which provides a neat solution to our problem. To define an alias for "WEB-INF/classes" just do the following:

1
2
3
4
...
WebAppContext wac = new WebAppContext();
wac.setResourceAlias("/WEB-INF/classes/", "/classes/");
...

Unfortunately this only works for single resources. While everything is fine when the folder "WEB-INF/classes" itself is accessed, the alias won't be applied when accessing resources contained within this folder, e.g. "WEB-INF/classes/MyManagedBean.class".

To tackle this problem I extended Jetty's WebAppContext to provide a means of pattern based alias resolution. The only overridden method is getResourceAlias():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class AliasEnhancedWebAppContext extends WebAppContext {

    @Override
    public String getResourceAlias(String alias) {

        @SuppressWarnings("unchecked")
        Map<String, String> resourceAliases = 
            (Map<String, String>) getResourceAliases();

        if (resourceAliases == null) {
            return null;
        }

        for (Entry<String, String> oneAlias : 
            resourceAliases.entrySet()) {

            if (alias.startsWith(oneAlias.getKey())) {
                return alias.replace(
                    oneAlias.getKey(), oneAlias.getValue());
            }
        }

        return null;
    }
}

Whenever an alias for a given resource is looked up, it is checked whether the resource name starts with one of the registered aliases. If that's the case, the aliased part will be replaced. Having registered the alias from the previous listing, e.g. "WEB-INF/classes/MyManagedBean.class" will be aliased with "classes/MyManagedBean.class".

It's certainly not perfect (e.g. nested replacements are not considered), but I would regard it good enough for being used in the scenario at hand. So let's look how all this fits together:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class JettyRunner {

    public static void main(String[] args) throws Exception {

        Server server = new Server();

        Connector connector = new SelectChannelConnector();
        connector.setPort(8080);
        connector.setHost("127.0.0.1");
        server.addConnector(connector);

        WebAppContext wac = new AliasEnhancedWebAppContext();
        wac.setContextPath("/myapp");
        wac.setBaseResource(
            new ResourceCollection(
                new String[] {"./src/main/webapp", "./target"}));
        wac.setResourceAlias("/WEB-INF/classes/", "/classes/");

        server.setHandler(wac);
        server.setStopAtShutdown(true);
        server.start();
        server.join();
    }
}

That way we are finally able to run a JSF application on an embedded Jetty instance, providing us with a very efficient way of development.

EL libraries

Unfortunately my happiness was short lasting as I ran into another problem: Using method parameters within EL expressions gave me parsing errors wrapped into a javax.faces.view.facelets.TagAttributeException.

The reason is that method invocations with parameters are a feature of Unified EL version 2.2 which is leveraged by JSF 2. As others already pointed out, you need to replace the EL JARs (API and impl) of you web container with the new ones.

Using Maven this can be done by adding the following dependencies to your project's pom.xml (if required, add the java.net Maven repository to your settings.xml first):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
<dependency>
    <groupId>javax.el</groupId>
    <artifactId>el-api</artifactId>
    <version>2.2</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>org.glassfish.web</groupId>
    <artifactId>el-impl</artifactId>
    <version>2.2</version>
    <scope>runtime</scope>
</dependency>
...

When working with the JSF 2 reference implementation Mojarra furthermore the expression factory to be used must be set to the one from the new EL implementation by specifying the following context parameter within your web.xml:

1
2
3
4
5
6
...
<context-param>
  <param-name>com.sun.faces.expressionFactory</param-name>
  <param-value>com.sun.el.ExpressionFactoryImpl</param-value>
</context-param>
...

Having done that, you are now able to use parametrized method invocations within EL expressions, which is especially useful when performing actions on the rows of a data table.

Saturday, November 21, 2009

Bookmark and Share

In a recent post I presented a generic DTO implementation which allows a type-safe way of accessing its contents.

The presented approach reduces the efforts of writing a lot of dedicated DTOs but comes at the cost that it is not obvious, which attributes are allowed to be put into or can be retrieved from a given DTO instance. Therefore methods using such a generic DTO as parameter or return value define a rather loose contract.

In the following I'm going to show a way to solve this problem. The basic idea is to introduce the concept of "attribute groups". Each attribute belongs to such a group, and each GenericDTO instance is created for exactly one attribute group.

Let's first define a marker interface AttributeGroup from which all concrete attribute groups will derive:

1
2
3
public interface AttributeGroup {

}

The Attribute class doesn't differ much from the version introduced in the first post. It's just parametrized with the type of group to which a given attribute belongs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class Attribute<G extends AttributeGroup, T> implements Serializable {

    private static final long serialVersionUID = 1L;

    private String name;

    public Attribute(String name) {

        if (name == null) {
            throw new IllegalArgumentException();
        }

        this.name = name;
    }

    public static <F extends AttributeGroup, S> Attribute<F, S> getInstance(
            String name) {
        return new Attribute<F, S>(name);
    }

    @Override
    public String toString() {
        return name;
    }

    // equals(), hashCode() ...
}

As in the previous post Attribute instances are declared as constants on interfaces, e.g. PersonAttributes. But now each of these interfaces extends AttributeGroup, while the Attribute instances are parametrized with the attribute group:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface PersonAttributes extends AttributeGroup {

    public static final Attribute<PersonAttributes, String> FIRST_NAME = 
        Attribute.getInstance("FIRST_NAME");

    public static final Attribute<PersonAttributes, Integer> AGE = 
        Attribute.getInstance("AGE");
}

...

public class OrderAttributes implements AttributeGroup {

    public static final Attribute<OrderAttributes, Long> 
        TOTAL_PRICE = Attribute.getInstance("TOTAL_PRICE");
}

Also the GenericDTO class now has a type parameter specifying for which attribute group a given instance is declared:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
public class GenericDTO<G extends AttributeGroup> implements Serializable {

    private static final long serialVersionUID = 1L;

    private Class<G> attributeGroup;

    private Map<Attribute<G, ?>, Object> attributes = new LinkedHashMap<Attribute<G, ?>, Object>();

    private GenericDTO(Class<G> attributeGroup) {
        this.attributeGroup = attributeGroup;
    }

    public static <B extends AttributeGroup> GenericDTO<B> getInstance(
            Class<B> clazz) {
        return new GenericDTO<B>(clazz);
    }

    public <T> GenericDTO<G> set(Attribute<G, T> identifier, T value) {

        attributes.put(identifier, value);

        return this;
    }

    public <T> T get(Attribute<G, T> identifier) {

        @SuppressWarnings("unchecked")
        T theValue = (T) attributes.get(identifier);

        return theValue;
    }

    public <T> T remove(Attribute<G, T> identifier) {

        @SuppressWarnings("unchecked")
        T theValue = (T) attributes.remove(identifier);

        return theValue;
    }

    public void clear() {
        attributes.clear();
    }

    public int size() {
        return attributes.size();
    }

    public Set<Attribute<G, ?>> getAttributes() {
        return attributes.keySet();
    }

    public boolean contains(Attribute<G, ?> identifier) {

        return attributes.containsKey(identifier);
    }

    @Override
    public String toString() {
        return attributeGroup.getSimpleName() + " [" + attributes + "]";
    }

    // equals(), hashCode() ...
}

That way it is now clear at compile time which attributes are supported by a given GenericDTO instance.

When for instance having a GenericDTO instance at hand, only attributes of the PersonAttributes group can be put into this DTO or can be retrieved from it. Trying to insert attributes of another group will yield in a compiler error:

1
2
3
4
5
6
7
8
9
...
GenericDTO dto = GenericDTO.getInstance(PersonAttributes.class);

//that's fine
dto.set(PersonAttributes.FIRST_NAME, "Bob").set(PersonAttributes.AGE, 28);

//compiler error
dto.set(OrderAttributes.TOTAL_PRICE, 9990);
...

By introducing the group concept Attribute declaration is a bit more verbose than in the first version, but real compile-time safety and more explicit contracts should be worth the effort, which is still way below than having to implement dedicated DTOs with getters and setters for each attribute as well as proper equals()-, hashCode()- and toString()-Methods.

What do you think – is a generic DTO implemented that way a good idea? As always I'm looking forward to receiving your feedback.

Saturday, November 7, 2009

Bookmark and Share

My article "Objekt: Zur Prüfung bitte!" covering the Bean Validation API (JSR 303) is available for download now. It originally appeared in Java Magazin 09.09.

Since the time of writing JSR 303 reached its final state, but besides some minor changes the article is still up to date (e.g. it's "Payload" instead of "ConstraintPayload" now). More in-depth information on using the Bean Validation API and its reference implementation Hibernate Validator 4 can be found in Hibernate Validator's reference guide, which I co-authored.

Sunday, October 25, 2009

Bookmark and Share

Update (10/21/2009): There is now a second part to this post, which can be found here.

Using data transfer objects (DTO's) is a common technique for transferring data between different modules of an application. Especially within distributed systems DTO's are of great help for transporting data over remote boundaries.

Classic DTO's are basically standard JavaBeans, having a getter/setter pair for each attribute. In larger applications usually quite a lot of DTO's are required, and implementing them is a tedious and time consuming task.

That's why the idea of a generic DTO was born – basically a key/value map, which can store any sort of attribute. This approach saves a lot of time for writing dedicated DTO's, but it comes at the cost of losing type safety at compile time.

A type-safe generic DTO

This problem can be solved by identifying attributes not with plain strings, but with unique parametrized identifiers. To do so, let's define a parametrized class Attribute as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Attribute<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    private final String name;

    private Attribute(String name) {

        if (name == null) {
            throw new IllegalArgumentException();
        }
        this.name = name;
    }

    public static <S> Attribute<S> getInstance(String name) {
        return new Attribute<S>(name);
    }

    @Override
    public String toString() {
        return name;
    }

    //equals(), hashCode() ...

}

The type parameter <T> defines the data type of a given attribute. For each required attribute a constant identifier should be created, e.g. in form of static members of an interface:

1
2
3
4
5
6
7
public interface CustomerAttributes {

    public final static Attribute<String> NAME = Attribute.getInstance("CustomerAttributes.Name");

    public final static Attribute<Integer> ID = Attribute.getInstance("CustomerAttributes.Id");

}

Note, that Attribute instances are retrieved using a static factory method instead of directly invoking the constructor. This allows for the type of <T> of the created Attribute being determined automatically by the compiler by using type argument inference.

Now let's have a look a the generic DTO itself:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
public class GenericDTO implements Serializable {

    private static final long serialVersionUID = 1L;

    private Map<Attribute<?>, Object> attributes = new LinkedHashMap<Attribute<?>, Object>();

    public <T> GenericDTO set(Attribute<T> identifier, T value) {

        attributes.put(identifier, value);

        return this;
    }

    public <T> T get(Attribute<T> identifier) {

        @SuppressWarnings("unchecked")
        T theValue = (T) attributes.get(identifier);

        return theValue;
    }

    public <T> T unset(Attribute<T> identifier) {

        @SuppressWarnings("unchecked")
        T theValue = (T) attributes.remove(identifier);

        return theValue;
    }

    public void clear() {
        attributes.clear();
    }

    public int size() {
        return attributes.size();
    }

    public Set<Attribute<?>> getAttributes() {
        return attributes.keySet();
    }

    public boolean contains(Attribute<?>... identifiers) {

        for (Attribute<?> oneIdentifier : identifiers) {
            if (!attributes.containsKey(oneIdentifier)) {
                return false;
            }
        }

        return true;
    }

    @Override
    public String toString() {
        return "GenericDTO [" + attributes + "]";
    }

    //equals(), hashCode() ...

}

As with the "classic" generic DTO the attributes are stored in a map (by using a LinkedHashMap the toString() method returns the attributes in order of insertion), but the set() and get() methods are parametrized with <T>.

That way for an Attribute<T> only a value of type T can be stored in or retrieved from the DTO. For instance the call

1
dto.set(CustomerAttributes.ID, "Bob"); 

would yield in a compiler error, as "Bob" is of type String instead of Integer.

Note that the unchecked casts within the get() and unset() methods are actually safe, as attributes can be put into the map only by using the type-safe set() method.

As convinience the set() method returns the DTO itself. That allows for chaining multiple invocations:

1
dto.set(CustomerAttributes.ID, 123).set(CustomerAttributes.NAME, "Bob");

Summary

By using unique parametrized attribute identifiers a generic DTO can be created, that ensures type safety when putting attributes into it or retrieving them from it.

But one problem remains: the contract of methods that use GenericDTO as parameter or return value is rather loose. It is not obvious, which attributes are allowed/can be expected within one given GenericDTO instance.

This might be documented using JavaDoc, but actually there is another interesting approach for tackling this problem, which is shown in this post.

Monday, August 24, 2009

Bookmark and Share

JSR 303 ("Bean Validation") is the upcoming standard for the declaration and evaluation of constraints at Java object models, either by using annotations or XML descriptors.

Having been in the works for quite a while, the Bean Validation API comprises a lot of the features of previously existing validation frameworks such as Hibernate Validator or the OVal framework.

One feature I'm particularly loving about OVal is not part of the new standard API: the possibility to define constraints using scripting or expression languages. This is quite practical, if the validation of one bean property depends on the value of another property of the same bean. Imagine for instance a calendar application, where the start date of a calendar event shall always be earlier than the end date.

Using the Bean Validation API, this problem could be solved by implementing a custom class-level constraint. Unfortunately this requires you to implement a dedicated constraint, whenever such inter-property validation is required.

With the help of a generic script annotation that takes an arbitrary script expression to be evaluated, this effort can be saved (at the cost of losing some compile-time safety, though). By using a simple Groovy expression for instance the constraint mentioned above could be expressed like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@ScriptAssert(lang = "groovy", script = "_this.startDate.before(_this.endDate)")
public class CalendarEvent {

    private String title;

    private Date startDate;

    private Date endDate;

    public CalendarEvent(String title, Date startDate, Date endDate) {

        this.title = title;
        this.startDate = startDate;
        this.endDate = endDate;
    }

    public String getTitle() {
        return title;
    }

    public Date getStartDate() {
        return startDate;
    }

    public Date getEndDate() {
        return endDate;
    }

}

But how to implement the ScriptAssert constraint shown in the example? Luckily the JSR 303 spec was designed to make it really easy to create custom constraints, so this is not a big dial. Basically it takes three steps to create a custom constraint:

  • define a constraint annotation
  • implement a validator class able to check the constraint
  • define an error message for the case that the constraint is violated

For the evaluation of script statements, we will leverage the scripting API defined by JSR 223 ("Scripting for the JavaTM Platform"), which is part of the JDK since Java 6. By doing so arbitrary scripting and expression languages, for which a JSR 223 compatible engine exists, can be used in the ScriptAssert annotation (a list of such engines can be found here).

Defining the annotation

At first we have to define the annotation type itself:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Target( { TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = ScriptAssertValidator.class)
@Documented
public @interface ScriptAssert {

    String message() default "{de.gmorling.beanvalidation.scriptassert}";

    Class<?>[] groups() default {};

    Class<? extends ConstraintPayload>[] payload() default {};

    String lang();

    String script();

    @Target( { TYPE })
    @Retention(RUNTIME)
    @Documented
    public @interface List {
        ScriptAssert[] value();
    }
}

The Bean Validation API requires each constraint annotation to define the three attributes

  • message (for specifying the key used to resolve the error text in case of constraint violations)
  • groups (allowing the constraint to be assigned to validation groups, if required)
  • payload (not used by the Bean Validation API itself, but might be used by validation clients to assign custom payloads to a constraint)

Besides these obligatory attributes we define the two attributes

  • lang (used to specify the name of this constraint's script language as understood by the JSR 223 ScriptEngineManager)
  • script (used to specify the script to be evaluated).

Furthermore we specify, that the constraint shall only be allowed at type declarations (by using the @Target meta-annotation) and that the class ScriptAssertValidator shall be used to evaluate the constraint.

By defining an additional inner annotation @List, which takes an array of ScriptAsserts as value, we follow the JSR's recommendation to provide a way for placing multiple constraints of the same type at one object.

Implementing the constraint validator

Having defined the constraint annotation it's time to implement the accompanying validator class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class ScriptAssertValidator implements
    ConstraintValidator<ScriptAssert, Object> {

    private String script;

    private String languageName;

    private ScriptEngineManager manager = new ScriptEngineManager();

    public void initialize(ScriptAssert constraintAnnotation) {

        this.script = constraintAnnotation.script();
        this.languageName = constraintAnnotation.lang();
    }

    public boolean isValid(Object value,
        ConstraintValidatorContext constraintValidatorContext) {

        ScriptEngine engine = manager.getEngineByName(languageName);

        if (engine == null) {
            throw new IllegalArgumentException(
                "No JSR 223 script engine found for language " + languageName);
        }

        engine.put("_this", value);

        try {
            return Boolean.TRUE.equals(engine.eval(script));
        } 
        catch (ScriptException e) {
            throw new RuntimeException(e);
        }
    }
}

In the initialize() method we store the given ScriptAssert annotation's values for the language name and the script contents.

The isValid() method is called by the Bean Validation runtime, whenever the constraint shall be evaluated. First we fetch a JSR 223 ScriptEngine for the given language. In order to make the object to be validated accessible inside the script, we put it into the engine's context under the name "_this". At last we call ScriptEngine's eval() method to evaluate the given script and check, whether the script's output equals to Boolean.TRUE.

Defining the error message

In case the constraint is violated, an error message is required to be put into the ConstraintViolation object created by the Bean Validation runtime. Error messages are defined in a resource file called ValidationMessages.properties (resp. localized derivations of that). So let's create that file with the following content:

1
de.gmorling.beanvalidation.scriptassert=Script statement "{script}" didn't evaluate to TRUE.

Testing the ScriptAssert annotation

Finally it's time to give our ScriptAssert constraint a little test run. Taking the CalendarEvent class from the introductory example, a test could look as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class CalendarEventTest {

    private static Validator validator;

    private static Date startDate;

    private static Date endDate;

    @BeforeClass
    public static void setUpValidatorAndDates() {

        validator = Validation.buildDefaultValidatorFactory().getValidator();

        startDate = new GregorianCalendar(2009, 8, 20).getTime();
        endDate = new GregorianCalendar(2009, 8, 21).getTime();
    }

    @Test
    public void validCalendarEvent() {

        CalendarEvent testEvent = 
            new CalendarEvent("Team meeting", startDate, endDate);

        assertTrue(validator.validate(testEvent).isEmpty());
    }

    @Test
    public void invalidCalendarEvent() {

        CalendarEvent testEvent = 
            new CalendarEvent("Team meeting", endDate, startDate);

        Set<ConstraintViolation<CalendarEvent>> constraintViolations = 
            validator.validate(testEvent);

        assertEquals(1, constraintViolations.size());
        assertEquals(
            "Script statement \"_this.startDate.before(_this.endDate)\" didn't evaluate to TRUE.",
            constraintViolations.iterator().next().getMessage());
    }

}

In validCalendarEvent() the event's start date is earlier than the end date, resulting in an empty set of constraint violations when validating the object. The opposite case is shown in invalidCalendarEvent(): We retrieve a ConstraintViolation as the event's start and end date are mixed up.

Note that as we are using Groovy as scripting language in the example, we need to have the Groovy library in the classpath (which already contains a JSR 223 compatible script engine implementation). Using Apache Maven, only the following dependency has to be added to your project's pom.xml:

1
2
3
4
5
6
7
8
...
<dependency>
    <groupId>org.codehaus.groovy</groupId>
    <artifactId>groovy-all</artifactId>
    <version>1.6.4</version>
    <scope>test</scope>
</dependency>
...

Trying it out yourself

I put all the sources of this post into a little project over at GitHub. A binary can be found in my Maven repository. So if want to give it a test run, first add the repo to your pom.xml/settings.xml:

1
2
3
4
5
6
7
8
...
<repositories>
    <repository>
        <id>http://gunnarmorling-maven-repo.googlecode.com/svn/repo/</id>
        <url>http://gunnarmorling-maven-repo.googlecode.com/svn/repo/</url>
    </repository>
</repositories>
...

Then simply add the following dependency to your POM:

1
2
3
4
5
6
7
...
<dependency>
    <groupId>de.gmorling</groupId>
    <artifactId>script-assert</artifactId>
    <version>0.2</version>
</dependency>
...

Furthermore you need the (runtime) dependency to a Bean Validation implementation (the script-assert project only has a dependency to the API). I recommend to take the reference implementation, so add a dependency to the RI itself as well as a binding for sl4j (used for logging purposes):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>4.0.0.Beta3</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-jdk14</artifactId>
    <version>1.5.6</version>
    <scope>runtime</scope>
</dependency>
...

As always any feedback on the usefulness of this post and any ideas for further improvement would be highly appreciated.

Sunday, August 23, 2009

Bookmark and Share

Finally I found some time to continue working on a little project of mine, scriptable dataset, which makes it possible to use script snippets (in languages such as JRuby, Groovy etc.) in your DBUnit dataset files. Imagine for instance, you were building a web shop application and wanted to insert an order issued 14 days ago into your order table. Using the scriptable dataset, you can do exactly that:

1
2
3
4
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
    <order product="CD player" orderdate="jruby:DateTime::now() - 14"/>
</dataset>

In comparison to the original release the 1.0 version contains basically some refactorings: ScriptableDataSetConfig got a new constructor, the Java 6 ServiceLoader mechanism is used to detect standard script invocation handlers, all dependencies were updated to the current versions and the entire code base was cleaned up a little bit.

Many thanks to Kevin Hutson, who contributed a test case for using Groovy as scripting language in a dataset file. It's really great to see, how GitHub is encouraging people to contribute to open source projects by making forking and merging that easy.

To allow for using the scriptable dataset in Maven based applications, I set up a Maven repository at Google code, which hosts the project's artifacts. Just add this repo to your pom.xml or settings.xml as shown below:

1
2
3
4
5
6
7
8
...
<repositories>
    <repository>
        <id>http://gunnarmorling-maven-repo.googlecode.com/svn/repo/</id>
        <url>http://gunnarmorling-maven-repo.googlecode.com/svn/repo/</url>
    </repository>
</repositories>
...

Then add scriptable dataset as dependency as well as a binding for sl4j, which is used for logging purposes:

1
2
3
4
5
6
7
8
9
10
11
12
...
<dependency>
    <groupId>de.gmorling</groupId>
    <artifactId>scriptable-dataset</artifactId>
    <version>1.0</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-jdk14</artifactId>
    <version>1.5.8</version>
</dependency>
...

An example for using the scriptable dataset is shown in the project's unit test ScriptableDataSetTest.

So feel free to give it a try. I'd be glad on any comments: do you like the idea of scripting in dataset files in general, what use cases could you think of, what place for improvement do you see?

Monday, August 10, 2009

Bookmark and Share

My second article in Java Magazin is out! It's named "Objekt: Zur Prüfung bitte!" and covers the upcoming Java standard for object validation, the Bean Validation API (JSR 303).

Using a simple web shop as example, the article starts with explaining Bean Validation basics (retrieving a Validator, using its methods for validating entire beans or single properties), followed by more detail information on validation groups and group sequences.

Next it is shown how to write a custom constraint annotation and its validation routine, followed by explaining the concept of constraint composition. Finally it is analyzed, how the Bean Validation API integrates with other standards such as JPA 2.0.

So get your copy of Java Magazin 09/2009 and let me know, how you like the article.

Thursday, April 9, 2009

Bookmark and Share

JAX-WS based web services normally run on a JEE web container or application server. That's great for production purposes, as those servers provide a very high level of scalability, security infrastructure, monitoring facilities etc.

But during development repeated deployments to a JEE container can be rather time consuming. JAX-WS' Endpoint class provides an interesting alternative here, as it allows to host JAX-WS web services within plain Java SE applications.

A web service hosted that way can very easily be launched and debugged from within your IDE for instance, which is great for development and testing purposes.

If you go with the code-first approach for web service development, things are really straight-forward:

1
2
3
4
5
6
7
8
9
10
11
public class SimpleServer {

    public static void main(String[] args) throws Exception {

        Endpoint endpoint = Endpoint.create(new ExamplePort());
        endpoint.publish("http://localhost:8080/example_app/ExampleService");

        System.out.println("Published service at http://localhost:8080/example_app/ExampleService");
    }

}

All you have to do is to create the end point by passing an instance of the port to be published (a class annotated with @WebService) and call the end point's publish() method.

Things are slightly more complicated if you prefer the contract-first web service style, meaning you start building your service with a WSDL file describing the service's interface and then generate service/port classes for it. In that case you have to specify the service's WSDL file as well as the QNames of the service and port to be published:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class SimpleServer {

    public static void main(String[] args) throws Exception {

        URL wsdlResource = 
            SimpleServer.class.getResource("/WEB-INF/wsdl/example.wsdl");

        List<Source> metadata = new ArrayList<Source>();

        Source source = new StreamSource(wsdlResource.openStream());
        source.setSystemId(wsdlResource.toExternalForm());
        metadata.add(source);

        Map<String, Object> properties = new HashMap<String, Object>();

        properties.put(
            Endpoint.WSDL_PORT, 
            new QName(
                "http://www.yournamespace.com/example",
                "ExamplePort"));
        properties.put(
            Endpoint.WSDL_SERVICE, 
            new QName(
                "http://www.yournamespace.com/example",
                "ExampleService"));

        Endpoint endpoint = Endpoint.create(new ExamplePort());
        endpoint.setMetadata(metadata);
        endpoint.setProperties(properties);

        endpoint.publish("http://localhost:8080/example_app/ExampleService");

        System.out.println("Published service at http://localhost:8080/example_app/ExampleService");
    }

}

Having launched the service it's a good idea to inspect the WSDL published by the JAX-WS runtime (e.g. at http://localhost:8080/example_app/ExampleService?WSDL). When using the JAX-WS reference implementation (RI) the file always starts with the comment "Published by JAX-WS RI ...", but in the contract-first scenario this shouldn't be followed by "Generated by JAX-WS RI ...".

JAX-WS RI is rather picky with its configuration, and if something is wrong, the runtime silently switches over to code-first mode, meaning the WSDL file is not the original one but was dynamically created from the port class. A common reason for this is not specifying the service and port QNames properly.

Here it would be great to have some kind of "force contract-first mode" option, which prevents the service from starting at all, if something is wrong with the configuration.

Tuesday, April 7, 2009

Bookmark and Share

When using the JUnit task for Apache Ant I recently came across the following error:

1
2
3
4
5
6
7
8
9
10
...
[junit] Error occurred during initialization of VM
[junit] Could not reserve enough space for object heap
[junit] Could not create the Java virtual machine.
[junit] java.io.FileNotFoundException: /home/.../junitvmwatcher995964737.properties (No such file or directory)
[junit]     at java.io.FileInputStream.open(Native Method)
[junit]     at java.io.FileInputStream.(FileInputStream.java:106)
[junit]     at java.io.FileReader.(FileReader.java:55)
[junit]     at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.executeAsForked(JUnitTask.java:1028)
...

At first I was rather distracted by the FileNotFoundException, but then I recognized that the message "Could not reserve enough space for object heap" might be a pointer to the actual problem.

My build file contained a target for the execution of JUnit tests roughly looking as follows:

1
2
3
4
5
6
7
8
9
10
11
12
...
<target name="junit" depends="jar">
    <junit printsummary="true" fork="true" forkmode="perTest" maxmemory="2048m">

        <classpath>...</classpath>

        <batchtest>
            <fileset dir="${src.dir}" includes="*Test.java"/>
        </batchtest>
    </junit>
</target>
...

When I decreased the value for the maxmemory attribute the error went away. I thought a rather large value here wouldn't do any harm, as I expected that only the actually required amount of memory would be allocated.

But obviously the JUnit task tries to allocate the total amount of memory up-front, causing the test to fail on my system, which only has 2 GB of RAM altogether.

Sunday, March 29, 2009

Bookmark and Share

When working with the Bean Validation API (JSR 303) it can be very practical to have the API sources at hand (e.g. as "Java Source Attachment" in Eclipse).

While the API binary can be retrieved from the JBoss Maven repository, no source JAR is deployed there as of March 2009.

But as the API sources are hosted at JBoss' public subversion repository, you can either read them online or check them out with any SVN client.

Using a SVN command line client the current release of the API – 1.0.CR1 – can be fetched by

1
svn co http://anonsvn.jboss.org/repos/hibernate/beanvalidation/tags/v1_0_CR1/

Monday, March 23, 2009

Bookmark and Share

JAX-WS is the standard API of the Java platform not only for the creation of web service providers but also for building web service clients. In the following I will show how to build and test a web service client using the JAX-WS reference implementation (RI) in conjunction with the Spring framework.

The example: A client for a simple shop web service

As example a simple client for an exemplary shop web service shall be built, that allows to search for products by their id. The WSDL looks as follows (this is a slightly simplified version of the WSDL from the shop service example which is part of the maven-instant-ws project):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?xml version="1.0" encoding="UTF-8"?>
<definitions 
    name="Products" 
    targetNamespace="http://www.gmorling.de/jaxwsonspring/products"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:tns="http://www.gmorling.de/jaxwsonspring/products"
    xmlns:products="http://www.gmorling.de/jaxwsonspring/products/types"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">

    <types>
        <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <xsd:import namespace="http://www.gmorling.de/jaxwsonspring/products/types"
                schemaLocation="products.xsd" />
        </xsd:schema>
    </types>

    <message name="GetProductByIdRequestMessage">
        <part name="body" element="products:GetProductByIdRequest" />
    </message>
    <message name="GetProductByIdResponseMessage">
        <part name="body" element="products:GetProductByIdResponse" />
    </message>

    <portType name="ProductsPortType">
        <operation name="GetProductById">
            <input message="tns:GetProductByIdRequestMessage" />
            <output message="tns:GetProductByIdResponseMessage" />
        </operation>
    </portType>

    <binding name="ProductsSoapBinding" type="tns:ProductsPortType">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
        <operation name="GetProductById">
            <soap:operation soapAction="GetProductById" />
            <input>
                <soap:body use="literal" />
            </input>
            <output>
                <soap:body use="literal" />
            </output>
        </operation>
    </binding>

    <service name="ProductsService">
        <port name="ProductsPort" binding="tns:ProductsSoapBinding">
            <soap:address location="TODO" />
        </port>
    </service>
</definitions>

The WSDL basically defines a single operation, GetProductById, that takes a GetProductByIdRequest object and returns a GetProductByIdResponse object. These types are specified in a separate XML schema:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?xml version="1.0" encoding="UTF-8"?>
<schema targetNamespace="http://www.gmorling.de/jaxwsonspring/products/types"
    xmlns="http://www.w3.org/2001/XMLSchema" xmlns:products="http://www.gmorling.de/jaxwsonspring/products/types">

    <!-- GetProductById -->
    <element name="GetProductByIdRequest">
        <complexType>
            <sequence>
                <element name="Id" type="int" />
            </sequence>
        </complexType>
    </element>
    <element name="GetProductByIdResponse">
        <complexType>
            <sequence>
                <element type="products:Product" name="Product" minOccurs="0" />
            </sequence>
        </complexType>
    </element>

    <!-- General-purpose types -->
    <complexType name="Product">
        <sequence>
            <element name="Id" type="int" />
            <element name="Name" type="string" />
            <element name="Price" type="decimal" />
            <element name="Size" type="string" minOccurs="0" />
        </sequence>
    </complexType>
</schema>

The request type is just a wrapper for an int parameter representing a product id, while the response type contains a Product element, which itself has a name, price etc.

Generating proxy classes

JAX-WS provides a tool called wsimport which takes the WSDL of a web service and generates proxy classes for the WSDL's service and port definitions. These can then be used to access the web service endpoint.

With the help of the JAX-WS Maven plugin the wsimport tool can easily be used in Maven based projects. Just configure the wsimport goal of the plugin in your project's pom.xml as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
<build>
    ...
    <plugins>
        ...
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jaxws-maven-plugin</artifactId>
            <executions>
                <execution>
                    <goals>
                        <goal>wsimport</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <wsdlDirectory>${basedir}/src/main/resources/wsdl</wsdlDirectory>
            </configuration>
        </plugin>
        ...     
    </plugins>
    ...
</build>
...

The WSDL to be processed can either be fetched directly from the actual web service endpoint or from a local directory (by specifying the wsdlDirectory property as shown in the example). I recommend to stick with the latter approach. That way your project can be built even if the service to be accessed is not available from your development environment.

During the "generate-sources" build lifecycle phase the plugin will generate

  • proxy classes for all service and port type declarations contained within the WSDL files in the specified directory
  • JAXB binding classes for all schema types used in the operations of that services

Using the proxy classes generated from the shop service WSDL it is not too hard to build a simple shop client:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package de.gmorling.jaxwsonspring;

import javax.xml.ws.BindingProvider;

import de.gmorling.jaxwsonspring.shop.products.ProductsPortType;
import de.gmorling.jaxwsonspring.shop.products.ProductsService;
import de.gmorling.jaxwsonspring.shop.products.types.GetProductByIdRequest;

public class ShopClient {

    private final static String END_POINT_URL = "http://localhost:8080/shopserver/Products";

    public String getProductNameByid(int productId) {

        GetProductByIdRequest request = new GetProductByIdRequest();
        request.setId(productId);

        ProductsService productsService = new ProductsService();
        ProductsPortType productsPort = productsService.getProductsPort();
        ((BindingProvider) productsPort).getRequestContext().put(
            BindingProvider.ENDPOINT_ADDRESS_PROPERTY, END_POINT_URL);

        return productsPort.getProductById(request).getProduct().getName();
    }
}

All you have to to do is to instantiate the ProductsService, retrieve the ProductsPort from it, set the endpoint address and call any of the port's operations.

Portability issues

This works basically pretty well, but I ran into a problem, as I tried to execute my project's binary on a different machine – suddenly the WSDL of the service couldn't be found. Searching the web a little bit I found out, that JAX-WS RI parses the WSDL each time a Service instance is created.

The WSDL's location is taken from an annotation of the generated Service class (ProductsService in this case), where it is unfortunately specified as an absolute path. That causes the Service initialization to fail if the project is moved to another directory or to another system, where the WSDL doesn't exist at the expected location.

This problem can be solved by specifying the WSDL location relatively when instantiating the Service class. This complicates the process of obtaining web service port references a little bit, therefore I thought it might be a good idea to make use of dependency injection (DI). That way the rather ugly API for setting the endpoint address can be hidden from the caller as well and DI finally allows to inject mock port implementations in unit tests.

Spring's JaxWsPortProxyFactoryBean

At first I considered building a custom solution using the Spring DI container, but then I stumbled upon Spring's JaxWsPortProxyFactoryBean that already provides DI services for JAX-WS client ports.

Using that bean a JAX-WS port can be configured within a Spring application context as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8"?>
<beans 
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="productsPort" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
        <property name="serviceInterface" value="de.gmorling.jaxwsonspring.shop.products.ProductsPortType" />
        <property name="wsdlDocumentUrl" value="wsdl/products.wsdl" />
        <property name="namespaceUri" value="http://www.gmorling.de/jaxwsonspring/shop/products" />
        <property name="serviceName" value="ProductsService" />
        <property name="endpointAddress" value="http://localhost:8080/jaxws-on-spring-server/Products" />
    </bean>
</beans>

So basically you have to configure the type of the port to be injected (the attribute name "serviceInterface" seams a bit irritating to me), the URL of the WSDL (e.g. identifying a classpath resource), namespaceUri and serviceName as specified in the WSDL file and finally the address of the endpoint to be used.

A word on thread safety

When configured as shown above Spring will use the singleton scope for the productsPort bean. That means the bean will exist only once and potentially be accessed from multiple threads at the same time.

Unfortunately the JAX-WS specification doesn't clearly say whether the generated service and port classes are thread-safe or not. Therefore one generally should assume that they aren't.

But after some searching, I found a comment by one of the JAX-WS RI developers stating, that the proxy classes of JAX-WS RI are thread-safe, as long as the request context of a port instance isn't modified. Assuming that no user of the bean modifies its request context (e.g. by re-setting the endpoint address) we are fine with the singleton scope for now.

Injecting JAX-WS client ports

Now let's rewrite the ShopClient class by having the productsPort bean injected into it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package de.gmorling.jaxwsonspring;

import javax.annotation.Resource;

import de.gmorling.jaxwsonspring.shop.products.ProductsPortType;
import de.gmorling.jaxwsonspring.shop.products.types.GetProductByIdRequest;

public class ShopClient {

    @Resource
    private ProductsPortType productsPort;

    public String getProductNameByid(int productId) {

        GetProductByIdRequest request = new GetProductByIdRequest();
        request.setId(productId);

        return productsPort.getProductById(request).getProduct().getName();
    }

}

Of course we need to configure ShopClient as Spring bean as well:

1
2
3
...
<bean id="shopClient" class="de.gmorling.jaxwsonspring.ShopClient" />
...

When creating the shopClient bean Spring will process the @Resource annotation (which stems from JSR 250: "Common Annotations for the JavaTM Platform") by populating the productsPort field with the bean of the same name.

Mocking web service requests in unit tests

Leveraging dependency the ShopClient class is greatly simplified now. As last step let's create a unit test for it.

To do so we should work with a mock implementation of the ProductsPortType interface. Working with a mock instead of accessing the real shop web service does not only increase the performance of the unit test. It also ensures, that the test result isn't dependent on the service's availability or its proper functioning.

For creating the mock we will use the freely available Mockito framework in the following (alternatively we could work with EasyMock or JMockit).

In the Spring application context for the unit test we specify that the productsPort bean shall be created by calling the method org.mockito.Mockito#mock(), which expects the class object of the object to be mocked as parameter:

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<beans 
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="productsPort" class="org.mockito.Mockito" factory-method="mock" >
        <constructor-arg index="0" value="de.gmorling.jaxwsonspring.shop.products.ProductsPortType" />
    </bean>

    <bean id="shopClient" class="de.gmorling.jaxwsonspring.ShopClient" />
</beans>

Next we have to define, how the mock shall behave, when it is called by the code under test. For doing so we inject the productsPort bean into our test class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package de.gmorling.jaxwsonspring;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

import java.math.BigDecimal;

import javax.annotation.Resource;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import de.gmorling.jaxwsonspring.shop.products.ProductsPortType;
import de.gmorling.jaxwsonspring.shop.products.types.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class ShopClientTest {

    @Resource
    private ProductsPortType productsPort;

    @Resource
    private ShopClient shopClient;

    @Before
    public void instructMock() {
        GetProductByIdResponse response = new GetProductByIdResponse();
        Product product = new Product();
        product.setId(1);
        product.setName("Jeans-Hose");
        product.setPrice(new BigDecimal("89.99"));
        product.setSize("L");
        response.setProduct(product);

        when(productsPort.getProductById(
            any(GetProductByIdRequest.class))).thenReturn(response);
    }

    @Test
    public void getProductName() {
        assertEquals("Jeans-Hose", shopClient.getProductNameByid(1));
    }

}

In the instructMock() method we first create a sample response object. Then we specify, that whenever the getProductById() of the mock is called, this response object shall be returned.

As the productsPort bean has singleton scope, the same instance of the bean will be injected into the shopClient bean. That way the shopClient bean will finally return the expected product name within the actual test method.

Conclusion

JAX-WS is a powerful API not only for the creation of web service providers but also for building web service clients. Unfortunately the devil is in the details – when not handled properly, JAX-WS will try to read WSDL files using absolute file pathes and setting end point addresses is not very intuitive as well.

Luckily the Spring framework comes to the rescue by enabling the creation of web service ports using dependency injection. That way obtaining port references is not only greatly simplified, it also allows mocking actual web service requests within unit tests.

The complete source code from this post can be downloaded here. As always I'd be happy about any comments and ideas for improvement.