Archive for November, 2009
Code readability: Uncover the conditions
Posted by Krzysztof Adamczyk in Articles on November 29, 2009
In this article I want to show a few techniques that can make you code more expressive and readable especially when dealing with conditions and business rules.
Let’s start with a simple example. Which of these two code snippets makes more sense to you ?
if (ratio > 13 && ratio < 23) {
doSomeStuff();
} else if (ratio <= 13) {
doOtherStuff();
}
or
final boolean ratioInSafeRange = ratio > 13 && ratio < 23;
final boolean ratioTooLow = ratio <= 13;
if (ratioInSafeRange) {
doSomeStuff();
} else if (ratioTooLow) {
doOtherStuff();
}
What are the magic numbers in the first example? Why do we need to do one thing or the other depending on these numbers? Of course, second version does not explain everything. We still must know a bit about the domain to understand this code, but it tells us that there probably is some range of values which is safe, and when the ratio is outside of this range we should act in some different way.
In second version, we gave the conditions their names, emphasising their meaning. Some would say that we can simply add comments that will explain what is going on. That’s true, but code changes quickly and comments become outdated and misleading in time. Comments are difficult to maintain and a false comment becomes rather an obstacle than help.
The solution presented above adds more expression to the code itself. It make the comment a part of the code, and therefore makes it more flexible. As the code evolves, developer can use refactoring techniques, bulk rename and so on to keep the comment-in-code up to date.
Now lets take a look at a bit more advanced example. Consider a banking system with the following domain interface:
interface Account {
public Date creationDate();
BigDecimal balance();
BigDecimal avarageMonthlyBalance();
void debit(BigDecimal amount);
void credit(BigDecimal amount);
}
We also have a domain service to make fund transfers:
class TransferService {
public void transfer(final Account source, final Account destination, final BigDecimal amount) {
source.debit(amount);
destination.credit(amount);
}
}
Now the business comes with a new requirement:
For every fund transfer from source account to destination account, a source account should pay a fee, unless the source account fulfills conditions of being a premium account. A premium account is an account which exists at least one year in the system and has an average monthly balance of $1000 or more for the last month.
We decide to put this logic into the TransferService, since the fee is to be paid for transfer and not for debit transaction. Let’s take a look at the first draft:
class TransferService {
private static final BigDecimal TRANSFER_FEE = BigDecimal.ONE;
public void transfer(final Account source, final Account destination, final BigDecimal amount) {
source.debit(amount);
destination.credit(amount);
final Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.YEAR, -1);
if (!(source.creationDate().compareTo(calendar.getTime()) <= 0 && source.avarageMonthlyBalance().compareTo(BigDecimal.valueOf(1000L)) > 0)) {
source.debit(TRANSFER_FEE);
}
}
}
After extracting the date computation into utility class, and applying the named condition pattern, we get the following:
public void transfer(final Account source, final Account destination, final BigDecimal amount) {
source.debit(amount);
destination.credit(amount);
final boolean accountExistsForAtLeatOneYear = source.creationDate().compareTo(DateTimeUtils.oneYearAgo()) <= 0;
final boolean monthlyBalanceGreaterThanRequired = source.avarageMonthlyBalance().compareTo(BigDecimal.valueOf(1000L)) > 0;
if (!(accountExistsForAtLeatOneYear && monthlyBalanceGreaterThanRequired)) {
source.debit(TRANSFER_FEE);
}
}
Just a small refactoring inside the if statement and here’s the final version of the method:
public void transfer(final Account source, final Account destination, final BigDecimal amount) {
source.debit(amount);
destination.credit(amount);
final boolean accountExistsForAtLeatOneYear = source.creationDate().compareTo(DateTimeUtils.oneYearAgo()) <= 0;
final boolean monthlyBalanceGreaterThanRequired = source.avarageMonthlyBalance().compareTo(BigDecimal.valueOf(1000L)) > 0;
if (!accountExistsForAtLeatOneYear || !monthlyBalanceGreaterThanRequired) {
source.debit(TRANSFER_FEE);
}
}
Much better, isn’t it?
What we achieved is a code which is much more readable and expressive than before. It reveals concepts that were hidden in the first version in a form of complex comparisons and logical operators.
But we can go further. In this case being or not a premium account is a business rule, a specification. It’s not programmers job to define what are the conditions and rules for an account to become premium. If so, lets make it an explicit business rule with a name which we can use talking to business people. When discussing with domain experts we will not talk in terms of IFs, but we can talk in terms of specifications, policies etc.
class PremiumAccountSpecification {
public boolean isSatisfiedBy(final Account candidate) {
final boolean accountExistsForAtLeatOneYear = candidate.creationDate().compareTo(DateTimeUtils.oneYearAgo()) <= 0;
final boolean monthlyBalanceGreaterThanRequired = candidate.avarageMonthlyBalance().compareTo(BigDecimal.valueOf(1000L)) >= 0;
return accountExistsForAtLeatOneYear && monthlyBalanceGreaterThanRequired;
}
}
and the TransferService now looks like this:
public void transfer(final Account source, final Account destination, final BigDecimal amount) {
source.debit(amount);
destination.credit(amount);
PremiumAccountSpecification premiumAccountSpecification = new PremiumAccountSpecification();
if (!premiumAccountSpecification.isSatisfiedBy(source)) {
source.debit(TRANSFER_FEE);
}
}
When writing software, we are constantly facing problem of losing important concepts in the code. It is important for the model to hide details behind abstractions, but also to make important things explicit. Business rules are a good example where explicitness pays off. The patterns presented above are useful not only in small scale where they do their job for readability and ease of maintenance of methods and classes, but also in the scale of the domain model, where they are first-class citizens (in form of Specifications) and do their contribution to the domain ubiquitous language.
Contract-first web services with JBoss 5, Metro & Spring
Posted by Krzysztof Adamczyk in Articles on November 27, 2009
In this article I want to show how to build a simple application deployed on JBoss 5 using Metro web services stack and Spring. The main purpose of this article is to show the configuration that needs to be done in order to create project structure, define dependencies and prepare deployable artifacts. That’s why you will find here much more XML than Java code (unfortunately). I chose to package the whole application as an EAR archive that in turn contains web application with our web services. Of course a WAR would be perfectly enough to show web services, but I want this project to be a base for future enhancement.
The complete source code from this example is available here.
What you need?
Step 1- Create Maven project
First of all let’s create the main project using Maven
mvn archetype:create -DgroupId=com.krzysztofadamczyk.playground.springmetrodemo -DartifactId=spring-metro-demo
Next we’ll changing packaging to “pom” in the main pom file
<packaging>pom</packaging>
We also have to add dependencyManagement section, where we put our dependencies settings:
For Spring:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> <version>2.5.6.SEC01</version> </dependency>
Metro:
<dependency> <groupId>com.sun.xml.ws</groupId> <artifactId>webservices-rt</artifactId> <version>1.5</version> </dependency> <dependency> <groupId>com.sun.tools.ws</groupId> <artifactId>webservices-tools</artifactId> <version>1.5</version> </dependency> <dependency> <groupId>javax.xml</groupId> <artifactId>webservices-api</artifactId> <version>1.5</version> </dependency> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1</version> <scope>provided</scope> </dependency>
For JAXWS-Spring integration we will exclude transitive dependencies to JAX-WS, since we already have JAX-WS RI in Metro:
<dependency> <groupId>org.jvnet.jax-ws-commons.spring </groupId> <artifactId>jaxws-spring</artifactId> <scope>runtime</scope> <version>1.8</version> <exclusions> <exclusion> <groupId>com.sun.xml.ws</groupId> <artifactId>jaxws-rt</artifactId> </exclusion> <exclusion> <groupId>com.sun.xml.ws</groupId> <artifactId>jaxws-local-transport</artifactId> </exclusion> <exclusion> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </exclusion> <exclusion> <groupId>junit</groupId> <artifactId>junit</artifactId> </exclusion> <exclusion> <groupId>javax.jws</groupId> <artifactId>jsr181-api</artifactId> </exclusion> <exclusion> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> </exclusion> <exclusion> <groupId>javax.xml.soap</groupId> <artifactId>saaj-api</artifactId> </exclusion> <exclusion> <groupId>com.sun.xml.messaging.saaj</groupId> <artifactId>saaj-impl</artifactId> </exclusion> <exclusion> <groupId>com.sun.xml.stream.buffer</groupId> <artifactId>streambuffer</artifactId> </exclusion> <exclusion> <groupId>com.sun.xml.stream</groupId> <artifactId>sjsxp</artifactId> </exclusion> <exclusion> <groupId>com.sun.org.apache.xml.internal</groupId> <artifactId>resolver</artifactId> </exclusion> <exclusion> <groupId>org.jvnet.staxex</groupId> <artifactId>stax-ex</artifactId> </exclusion> <exclusion> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> </exclusion> </exclusions> </dependency>
We must also declare repository for JAXWS-Spring integration:
<repositories>
<repository>
<id>maven2-repository.dev.java.net</id>
<name>Java.net Maven 2 Repository</name>
<url>http://download.java.net/maven/2</url>
</repository>
</repositories>
Step 2 – Create web application project
mvn archetype:create -DartifactId=services -DarchetypeArtifactId=maven-archetype-webapp
Add dependencies (dependencies are marked optional, because I don’t want them to go into WAR file – I’ll keep them on EAR level for future use by other modules):
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> <optional>true</optional> </dependency> <!-- JAX-WS-Spring integration --> <dependency> <groupId>org.jvnet.jax-ws-commons.spring</groupId> <artifactId>jaxws-spring</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.sun.xml.ws</groupId> <artifactId>webservices-rt</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>javax.xml</groupId> <artifactId>webservices-api</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.sun.tools.ws</groupId> <artifactId>webservices-tools</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> </dependencies>
We will also define ant task that will import our WSDL and create corresponding Java classes:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>generate-bindings</id>
<phase>generate-sources</phase>
<configuration>
<tasks>
<mkdir dir="${basedir}/target/generated-sources"></mkdir>
<mkdir dir="${basedir}/target/throwaway-classes"></mkdir>
<taskdef name="wsimport" classname="com.sun.tools.ws.ant.WsImport">
<classpath refid="maven.compile.classpath" />
<classpath refid="maven.plugin.classpath" />
</taskdef>
<wsimport
wsdl="${basedir}/src/main/webapp/WEB-INF/wsdl/EchoService.wsdl"
sourcedestdir="${basedir}/target/generated-sources"
destdir="${basedir}/target/throwaway-classes" fork="true"
extension="true"></wsimport>
</tasks>
<sourceRoot>${basedir}/target/generated-sources</sourceRoot>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
We don’t want to mix “hand-written” and generated classes, and therefore we will use separate source directories to keep them. As there can be only one sourceDirectory defined in build section, we have to use the following plug-in to define second source directory:
<build>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${basedir}/target/generated-sources</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
We have to configure our web application in web.xml. Things to notice here:
- org.springframework.web.context.ContextLoaderListener
Which initializes Spring application context - com.sun.xml.ws.transport.http.servlet.WSSpringServlet
which handles requests and integrates JAX-WS with Spring
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Spring + Metro on JBoss demo</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>jaxws-servlet</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSSpringServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>jaxws-servlet</servlet-name>
<url-pattern>/echoService</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>redirect.jsp</welcome-file>
</welcome-file-list>
</web-app>
Step 3 – Create EAR project
mvn archetype:create -DartifactId=ear
Ear projects dependencies will be put into EAR file. The main parts of the pom file are shown below:
....
<packaging>ear</packaging>
<dependencies>
<dependency>
<groupId>com.krzysztofadamczyk.playground.springmetrodemo</groupId>
<artifactId>services</artifactId>
<type>war</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</dependency>
<dependency>
<groupId>org.jvnet.jax-ws-commons.spring</groupId>
<artifactId>jaxws-spring</artifactId>
</dependency>
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>webservices-rt</artifactId>
</dependency>
<dependency>
<groupId>com.sun.tools.ws</groupId>
<artifactId>webservices-tools</artifactId>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
<modules>
<webModule>
<groupId>com.krzysztofadamczyk.playground.springmetrodemo</groupId>
<artifactId>services</artifactId>
<contextRoot>/spring-metro-webservices</contextRoot>
</webModule>
</modules>
</configuration>
</plugin>
</plugins>
</build>
Step 4 – prepare contracts
Now as our project structure is more or less done we can focus on preparing contracts for the web service. In this example we will create a simple echo service which simply returns the given string with “echo” prefix. Types are defined into EchoTypes.xsd file:
<?xml version="1.0" encoding="UTF-8"?> <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.krzysztofadamczyk.com/echo/" xmlns:tns="http://www.krzysztofadamczyk.com/echo/" elementFormDefault="qualified"> <xs:element name="EchoRequest"> <xs:complexType> <xs:all> <xs:element name="text" type="xs:string" /> </xs:all> </xs:complexType> </xs:element> <xs:element name="EchoResponse"> <xs:complexType> <xs:all> <xs:element name="text" type="xs:string" /> </xs:all> </xs:complexType> </xs:element> </schema>
The WSDL file is presented below:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.krzysztofadamczyk.com/echo/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:echo="http://www.krzysztofadamczyk.com/echo/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="echo" targetNamespace="http://www.krzysztofadamczyk.com/echo/"> <wsdl:types> <xsd:schema> <xsd:import namespace="http://www.krzysztofadamczyk.com/echo/" schemaLocation="EchoTypes.xsd" /> </xsd:schema> </wsdl:types> <wsdl:message name="EchoRequest"> <wsdl:part name="EchoRequest" element="echo:EchoRequest" /> </wsdl:message> <wsdl:message name="EchoResponse"> <wsdl:part name="EchoResponse" element="echo:EchoResponse" /> </wsdl:message> <wsdl:portType name="EchoPort"> <wsdl:operation name="sayEcho"> <wsdl:input message="tns:EchoRequest" /> <wsdl:output message="tns:EchoResponse" /> </wsdl:operation> </wsdl:portType> <wsdl:binding name="echoSOAP" type="tns:EchoPort"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="sayEcho"> <soap:operation soapAction="http://www.krzysztofadamczyk.com/echo/SayEcho" /> <wsdl:input> <soap:body use="literal" /> </wsdl:input> <wsdl:output> <soap:body use="literal" /> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="EchoService"> <wsdl:port binding="tns:echoSOAP" name="echoSOAP"> <soap:address location="http://www.example.org/" /> </wsdl:port> </wsdl:service> </wsdl:definitions>
Step 5 – create service endpoint implementation
After building the project with mvn install you can see a few Java classes generated in target\generated-sources\. EchoPort is our generated Service Endpoint Interface. We will now create the service implementation as follows:
package com.krzysztofadamczyk.playground.springmetrodemo;
import javax.jws.WebService;
import com.krzysztofadamczyk.echo.EchoPort;
import com.krzysztofadamczyk.echo.EchoRequest;
import com.krzysztofadamczyk.echo.EchoResponse;
@WebService(name = "EchoPort", targetNamespace = "http://www.krzysztofadamczyk.com/echo/",
endpointInterface = "com.krzysztofadamczyk.echo.EchoPort")
public class EchoServiceImpl implements EchoPort {
public EchoResponse sayEcho(final EchoRequest echoRequest) {
final EchoResponse result = new EchoResponse();
result.setText("echo: " + echoRequest.getText());
return result;
}
}
Step 6 – define application context
Now it’s time to define application context. Here we take advantage of JAXWS-Spring integration using specialized schema to define our web service. Note that our endpoint implementation is a standard Spring bean and we can use here dependency injection or any other Spring technique.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ws="http://jax-ws.dev.java.net/spring/core"
xmlns:wss="http://jax-ws.dev.java.net/spring/servlet"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://jax-ws.dev.java.net/spring/core http://jax-ws.dev.java.net/spring/core.xsd
http://jax-ws.dev.java.net/spring/servlet
http://jax-ws.dev.java.net/spring/servlet.xsd">
<wss:binding url="/echoService">
<wss:service>
<ws:service bean="#echoService" />
</wss:service>
</wss:binding>
<!-- this bean implements web service methods -->
<bean id="echoService" class="com.krzysztofadamczyk.playground.springmetrodemo.EchoServiceImpl" />
</beans>
Step 7 – deploy and test project
After successfull build, copy EAR file (which can be found in ear/target) into jboss_home/server/default/deploy, and start server. Run SoapUI and create new project with the following WSDL location:
http://localhost:8080/spring-metro-webservices/echoService?wsdl
Where:
- spring-metro-webservices – is the web application context root defined in EAR project pom
- echoService – is an URL pattern (defined in web.xml, associated with WSSpringServlet), and also defined as binding URL in applicationContext.xml
SoapUI will generate a sample request for you. The result looks as follows:
![]() |
| From Blog |
First steps with Groovy
Posted by Krzysztof Adamczyk in Articles on November 27, 2009
Inspired by Scott Davies and his great talk during Java Developers’ Day in Krakow I decided to try out Groovy. As a first step I want to create a running application which contains both Java and Groovy classes talking to each other. I’ll also take Scott’s idea to use a Geocoding RESTful web service to show how simple dealing with XML in Groovy is. So – let’s start.
- Step 0 – Download software
- Step 1 – create Maven project with GMaven
mvn archetype:generate -DarchetypeGroupId=org.codehaus.groovy.maven.archetypes -DarchetypeArtifactId=gmaven-archetype-basic -DarchetypeVersion=1.0-rc-5 -DgroupId=com.krzysztofadamczyk.playground.geocoder -DartifactId=geocoder
- Step 2 – build project & import to Eclipse
Add “java” directories to both src/main and src/test directories
mvn install
mvn -Declipse.downloadSources eclipse:eclipse
- Step 3 – implement domain class in Java
package com.krzysztofadamczyk.playground.geocoder.domain;
public class Location {
private final double longitude;
private final double latitude;
public Location(final double longitude, final double latitude) {
this.longitude = longitude;
this.latitude = latitude;
}
public double getLongitude() {
return this.longitude;
}
public double getLatitude() {
return this.latitude;
}
public String toString() {
return "Location [latitude=" + this.latitude + ", longitude=" + this.longitude + "]";
}
}
- Step 4 – implement web service client in Groovy
package com.krzysztofadamczyk.playground.geocoder
import com.krzysztofadamczyk.playground.geocoder.domain.Location
public class GroovyGeocoder{
private final def BASEURL = "http://worldkit.org/geocoder/rest/?city=";
public def Location getLocation(String city, String twoLetterCountryCode) {
def wsAddress = BASEURL + city + "," + twoLetterCountryCode
def geocoded = wsAddress.toURL().text
def RDF = new XmlSlurper().parseText(geocoded)
new Location(Double.valueOf(RDF.Point.long.text() ), Double.valueOf(RDF.Point.lat.text()))
}
}
- Step 5 – Implement main class in Java
package com.krzysztofadamczyk.playground.geocoder.runner;
import com.krzysztofadamczyk.playground.geocoder.GroovyGeocoder;
import com.krzysztofadamczyk.playground.geocoder.domain.Location;
public class Runner {
public static void main(final String[] args) {
final GroovyGeocoder geocoder = new GroovyGeocoder();
final Location location = geocoder.getLocation("Krakow", "PL");
System.out.println(location);
}
}
Running this simple example produces the following output:
Location [latitude=50.0833333, longitude=19.9166667]

Recent comments