Eclipse Maven Tycho Xtext Archetype

2013/12/25

Xtext comes with pretty good documentation, but if you want to automate the build for your little new DSL, you’re drifting into deep water. There is some documentation on the Net, but even if you are an advanced Maven user, it’s easy to get lost with the Tycho plugin.

That’s why I made a Maven Archetype that creates a standard multi-module Maven layout and that also includes a P2 repository project, which is missing when you use the standard Eclipse Xtext wizard.

If you just want to use the default settings, simply execute the following on the command line:

mvn archetype:generate \
  -DarchetypeGroupId=org.fuin.archetypes \
  -DarchetypeArtifactId=emt-xtext-archetype \
  -DarchetypeVersion=0.1.0

It will generate the following project structure:

>com.mycompany.mydsl
|-- com.mycompany.mydsl.dsl
|-- com.mycompany.mydsl.repository
|-- com.mycompany.mydsl.sdk
|-- com.mycompany.mydsl.tests
|-- com.mycompany.mydsl.ui
`-- mydsl-test
.mydsl Maven parent project. [Maven project]
.mydsl.dsl Grammar and base classes for the DSL [Tycho 'eclipse-plugin']
.mydsl.repository Creates a P2 repository. [Tycho 'eclipse-repository']
.mydsl.sdk Eclipse feature project [Tycho 'eclipse-feature']
.mydsl.tests Unit test project. [Tycho 'eclipse-test-plugin']
.mydsl.ui UI related parts. [Tycho 'eclipse-plugin']
.mydsl-test Example DSL project. [Eclipse project]

When you start creating a real project, you should also add the other parameters that are available for the generate command.

For a full description of the archetype, just visit the project page on GitHub: https://github.com/fuinorg/emt-xtext-archetype

Strategic Domain Driven Design with Context Mapping

2013/11/30

A very nice article about the role of bounded contexts in Domain Driven Design (DDD): Strategic Domain Driven Design with Context Mapping (Alberto Brandolini)

Finding methods calls programmatically

2013/10/01

In the current project a defect was raised with the following exception attached:

java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

After I dug into the code, I found the cause was simple. There was no rounding mode given for calculations that might produce big decimals, like in this example:

BigDecimal.ONE.divide(BigDecimal.valueOf(3));

Every senior developer knows about this trap, but it’s still easy to forget. A default of BigDecimal.ROUND_HALF_UP, applied when no rounding mode is defined explicitly, would have made the method more safe to use.

How is it possible to prevent such failures in the future and avoid dividing a single big decimal parameter ad infinitum? One could use Checkstyle rules, use FindBugs rules or create a simple unit test.

I chose the unit test, so the question became “How can I find all the methods that call a given method in Java?” This is not possible with the standard Reflection API, but I had already used OW2′s ASM for such tasks, so it wasn’t too hard to create a JUnit assertion for it.

Just include this in your unit tests:


// Path to your project's '*.class' files
final File classesDir = new File("target/classes");

// Can be used to exclude some files/packages
final FileFilter fileFilter = new FileFilter() {
    @Override
    public boolean accept(File file) {
	return !file.getPath().contains("my/pkg/to/exclude");
    }
};

// Define methods to find
final MCAMethod divide = new MCAMethod("java.math.BigDecimal",
	"java.math.BigDecimal divide(java.math.BigDecimal)");

final MCAMethod setScale = new MCAMethod("java.math.BigDecimal",
	"java.math.BigDecimal setScale(int)");

// Fails if any class calls one of the two methods
AssertUsage.assertMethodsNotUsed(classesDir, fileFilter, 
                                 divide, setScale);

The full source code can be found at GitHub.

EclipseLink: How to get the SQL translated with the arguments for a Query?

2013/09/12

The documentation at the EclipseLink Wiki is not very helpful: http://wiki.eclipse.org/EclipseLink/FAQ/JPA#How_to_get_the_SQL_for_a_Query.3F

It says: “To get the SQL translated with the arguments you need a DatabaseRecord with the parameter values.“.

// BEGIN Snippet from the Wiki

Session session = em.unwrap(JpaEntityManager).getActiveSession();

DatabaseQuery databaseQuery = 
  ((EJBQueryImpl)query).getDatabaseQuery();

String sqlString = databaseQuery
  .getTranslatedSQLString(session, 
       recordWithValues);

// END Snippet from the Wiki

But where to get the recordWithValues variable? Actually the solution is hard to find, but simple: databaseQuery.getTranslationRow()

// This does the trick...

String sqlString = databaseQuery
  .getTranslatedSQLString(session, 
       databaseQuery.getTranslationRow());

// ... to replace the '?' 

Mixins with pure Java

2013/06/17

Implementation of mixins using AOP (AspectJ) or source-code modification (JaMoPP)

In object-oriented programming languages, a mixin refers to a defined amount of functionality which can be added to a class. An important aspect of this is that it makes it possible to concentrate more on the properties of a particular behaviour than on the inheritance structures during development.

In Scala for example, a variant of mixins can be found under the name of “traits”. Although Java does not provide direct support for mixins, these can easily be added on with a few annotations, interfaces and some tool support.

Occasionally you read in a few online articles that mixins are incorporated into Java version 8. Unfortunately, this is not the case. A feature of the Lambda project (JSR-335) are the so-called “Virtual Extension Methods” (VEM).

Whilst these are similar to mixins, they do have a different background and are significantly more limited in functionality. The motivation for the introduction of VEMs is the problem of backward compatibility in the introduction of new methods in interfaces.

As “real” mixins are not expected in the Java language in the near future, this article intends to demonstrate how it is already possible to create mixin support in Java projects now, using simple methods. To do this, we will discuss two approaches: using AOP with AspectJ and using source-code modification with JaMoPP.

Why not just inheritance?

When asked at an event “What would you change about Java if you could reinvent it?James Gosling, the inventor of Java is said to have answered “I would get rid of the classes“.

After the laughter had died down, he explained what he meant by that: inheritance in Java, which is expressed with the “extends” relationship, should – wherever possible – be replaced by interfaces [Why extends is evil].

Any experienced developer knows what he meant here: inheritance should be used sparingly. It is very easy to misuse it as a technical construct to reuse code, and not to model a technically motivated parent-child relationship with it.

But even if one considers such a technically motivated code reuse as legitimate, one quickly reaches its limits, as Java does not allow multiple inheritance.

Mixins are always useful if several classes have similar properties or define a similar behaviour, but these cannot be reasonably modelled simply via slim relationship hierarchies.

In English, terms which end in “able” (e.g. “sortable”, “comparable” or “commentable”) are often an indicator for applications of mixins. Also, when starting to write “Utility” methods in order to avoid a code duplication in the implementation of interfaces, this can be an indication of a meaningful case of application.

Mixins with AOP

So-called Inter-type declarations are an extremely simple possibility for implementing mixins, offered by the AspectJ Eclipse project. With these, it is possible – among other things – to add new instance variables and methods to any target class.

This will be shown in the following, based on a small example in Listing 1. For this, we will use the following terms:

  • Basis-Interface Describes the desired behaviour. Classes which the mixin should not use can use this interface.
  • Mixin-Interface Intermediate interface used in the aspect and implemented by classes which the mixin is to use.
  • Mixin-Provider Aspect which provides the implementation for the mixin.
  • Mixin-User Class which uses (implements) one or more mixin interfaces.

// === Listing 1 ===

/** Base-Interface */
public interface Named {
    public String getName();
}

/** Mixin-Interface */
public interface NamedMixin extends Named {
}

/** Mixin-Provider */
public aspect NamedAspect {
    private String NamedMixin.name;
    public final void NamedMixin.setName(String name) {
        this.name = name;
    }
    public final String NamedMixin.getName() {
        return name;
    }   
}

/** Mixin-User */
public class MyClass implements NamedMixin {
   // Could have more methods or use different mixins
}

Listing 1 shows a complete AOP-based mixin example. If AspectJ is set up correctly, the following source text should compile and run without errors:


MyClass myObj = new MyClass();
myObj.setName("Abc");
System.out.println(myObj.getName());

It is possible to work quite comfortably with AOP variants, but there are also a few disadvantages which will be explored here.

First of all, inter-type declarations cannot deal with generic types in the target class. This is not absolutely necessary in many cases, but can be very practical. For example, it is possible to define the “Named” interface just as well with a generic type instead of “String”. It would then define the behaviour for any name types. The class used could then determine how the type of name should look.

A further disadvantage is that the methods generated by AspectJ follow their own naming conventions. This makes it difficult to search the classes using reflection, as you would have to reckon with method names such as “ajc$interMethodDispatch …”

Last but not least, without the support of the development environment, you cannot see the source code in the target class and are dependent on the interface declaration alone. This could, however, be seen as an advantage, since the using classes contain less code.

Appearance: Java Model Parser and Printer (JaMoPP)

An alternative to the implementation of mixins with AspektJ is offered by Java Model Parser and Printer (JaMoPP). Simply put, JaMoPP can read Java source code, present it as an object graph in the memory and transform (i.e. write) it back into text.

With JaMoPP, it is therefore possible to programmatically process Java code and thus automate refactoring or implement your own code analyses, for example. Technologically, JaMoPP is based on the Eclipse Modeling Framework (EMF) and EMFText. JaMoPP is jointly developed by the Technical University of Dresden and DevBoost GmbH and is freely available on GitHub as an open-source project.

Mixins with JaMoPP

In the following, we would like to take up the example from the AOP mixins and expand this slightly. For this, we will first define a few annotations:

  • @MixinIntf Indicates a mixin interface.
  • @MixinProvider Indicates a class which provides the implementation for a mixin. The implemented mixin interface is specified as the only parameter.
  • @MixinGenerated Marks methods and instance variables which have been generated by the mixin. The only parameter is the class of the mixin
  • provider.

In the following, we will also be expanding the interfaces and classes from Listing 1 with a generic type for the name. Only the class using the mixin defines which concrete type the name should actually have.


// === LISTING 2 ===

/** Base-Interface (Extended with generic parameter) */
public interface Named<T> {
    public T getName();
}

/** Mixin-Interface */
@MixinIntf 
public interface NamedMixin<T> extends Named<T> {
}

/** Mixin-Provider */
@MixinProvider(NamedMixin.class)
public final class NamedMixinProvider<T> implements Named<T> {

    @MixinGenerated(NamedMixinProvider.class)
    private T name;

    @MixinGenerated(NamedMixinProvider.class)
    public void setName(T name) {
        this.name = name;
    }

    @Override
    @MixinGenerated(NamedMixinProvider.class)
    public T getName() {
        return name;
    }
    
}

/** Special name type (Alternative to String) */
public final class MyName {
    private final String name;

    public MyName(String name) {
        super();
        if (name == null) {
            throw new IllegalArgumentException("name == null");
        }
        if (name.trim().length() == 0) {
            throw new IllegalArgumentException("name is empty");
        }
        this.name = name;
    }

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

}

In the class which the mixin is to use, the mixin interface is now implemented again as shown in Listing 3. In order to “blend” the fields and methods defined by the mixin provider into the MyClass class, a code generator is used.

With the help of JaMoPP, this modifies the MyClass class and adds the instance variables and methods provided by the mixin provider.


// === LISTING 3 ===

/** Mixin-User */
public class MyClass implements NamedMixin<MyName> {
    // Could have more methods or use different mixins
}

In doing this, the code generator does the following. It reads the source code of every class, similarly to the normal Java compiler, and, in doing so, examines the amount of implemented interfaces.

If a mixin interface is present, i.e. an interface with the annotation @MixinIntf, the corresponding provider is found and the instance variables and methods are copied into the class which is implementing the mixin.

In order to initiate the generation of mixin codes, there are currently two options: using an Eclipse plug-in directly when saving or as a Maven plug-in as part of the build.

Installation instructions and the source code of both plug-ins can be found on GitHub in the small SrcMixins4J project. There is also an on-screen video available there, which demonstrates the use of the Eclipse plug-in. Listing 4 shows the how the modified target class then looks.


// === LISTING 4 ===

/** Mixin-User */
public class MyClass implements NamedMixin<MyName> {

    @MixinGenerated(NamedMixinProvider.class)
    private MyName name;

    @MixinGenerated(NamedMixinProvider.class)
    public void setName(MyName name) {
        this.name = name;
    }

    @Override
    @MixinGenerated(NamedMixinProvider.class)
    public MyName getName() {
        return name;
    }

}

If the mixin interface is removed from the “implements” section, all of the provider’s fields and methods annotated with “@MixinGenerated” will be deleted automatically. Generated code can be overridden at any time by removing the “@MixinGenerated” annotation.

 

Click on the following image to open a Flash video that demonstrates the Eclipse plugin:

Screenshot Eclipse

Conclusion

As native support of mixins in the Java language standard is not expected in the foreseeable future, it is currently possible to make do with just some AOP or source-code generation. Which of the two options you choose depends essentially on whether you prefer to keep the mixin code separate from your own application code or whether you want them directly in the respective classes.

In any case, the speed of development is significantly increased and you will concentrate less on inheritance hierarchies and more on the definition of functional behaviour.

Neither approach is perfect. In particular, conflicts are not automatically resolved. Methods with the same signature from different interfaces which are provided by different mixin providers will, for example, lead to an error in a class which uses both mixins.

Those seeking anything more would have to transfer to another language with native mixin support, such as Scala.

SLF4J Logging in Eclipse Plugins

2013/01/02

Developing with Maven and pure Java libraries all the time, I never thought it could be a problem to issue a few log statements when developing an Eclipse plugin. But it looks like in the imaginary of an Eclipse developer everything is always inside the Eclipse environment and nothing is outside the Eclipse universe.

If you search for the above headline using Google, one of the first articles you’ll find is one about the “platform logging facility”. But what about 3rd libraries? They cannot use an Eclipse-based logging framework.

In my libraries I use the SLF4J API and leave it up to the user to decide what logging implementation (Log4J, Logback, JDK) he or she wants to use. And that’s exactly what I want to do in Eclipse. It was hard to figure out exactly how to do it, but here are the pieces of that puzzle.

Phase 1: Development

This describes the steps during the development phase of your custom plugin.

Step 1: Get your libaries into a P2 repository

Everything you want to use in Eclipse has to be installed from a P2 repository. But most of the libaries I use are in a Maven repository. As far as I know there is no such thing as a main P2 repository similar to the “Maven Central,” and all libraries I found in P2 repositories were pretty old. So you have to create one by yourself.

Luckily there is a Maven plugin called p2-maven-plugin that converts all your Maven JARs into a single P2 repository. You can upload the plugin to a folder of your website or simply install it from your local hard drive.

For this example you’ll need the following libraries:

  • org.slf4j:slf4j-api:1.6.6
  • org.slf4j:slf4j-log4j12:1.6.6
  • log4j:log4j:1.2.17
  • org.ops4j.pax.logging:pax-logging-api:1.7.0
  • org.ops4j.pax.logging:pax-logging-service:1.7.0
  • org.ops4j.pax.confman:pax-confman-propsloader:0.2.2

Format “groupId:artifactid:version” is as used for the “p2-maven-plugin.” To skip this step you could also use http://www.fuin.org/p2-repository/.

Step 2: Install the SLF4J API in the Eclipse IDE

  1. Select “Help / Install New Software…”.
    Eclipse / Help / Install
  2. Add the P2 repository URL and install the “slf4j-api”—you could directly use the folder from Step 1 with a file URL like this: “file:/pathtoyour/p2-repository/”.Instal Slf4J API
  3. Add the freshly installed “slf4j.api” to your MANIFEST.MF.Dependencies in MANIFEST.MF
  4. Start using SLF4J logs in your code as usual.

Phase 2: Production

This describes the tasks a user of your custom plugin has to complete to start logging with Log4J. The following assumes that your custom plugin is already installed.

Step 1: Install the log libraries in the Eclipse IDE

  1. Select “Help / Install New Software…”.Eclipse / Help / Install
  2. Install the “Equinox Target Components” from the Eclipse Update Site.Install Equinox Target Components
  3. Add the P2 repository URL and install the following plugins:
    • Apache Log4j
    • OPS4J Pax ConfMan–Properties Loader
    • OPS4J Pax Logging–API
    • OPS4J Pax Logging–Service

    Install Log Libs

Step 2: Configure PAX Logging

  1. Set the location for your log configuration in the “eclipse.ini” as “vmarg"

    -vmargs
    -Xms40m
    -Xmx512m
    -Dbundles.configuration.location=<config-dir>

  2. Create a folder named “services” in the above “config-dir.”
  3. Create Log4J properties named “org.ops4j.pax.logging.properties” in “services.”

    log4j.rootLogger=INFO, FILE
    log4j.appender.FILE=org.apache.log4j.FileAppender
    log4j.appender.FILE.File=<path-to-your-log>/example.log
    log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
    log4j.appender.FILE.layout.ConversionPattern=%d{yyyy/MM/dd HH:mm:ss,SSS} [%t] %-5p %c %x - %m%n
    log4j.logger.your.package=DEBUG

Step 3: Activate PAX Logging

  1. Open the “Console” view.Show Console View
  2. Select the “Host OSGI Console.”Select OSGI Console
  3. Start the following bundles:
    start org.eclipse.equinox.cm
    start org.ops4j.pax.logging.pax-logging-api
    start org.ops4j.pax.logging.pax-logging-service
    start org.ops4j.pax.configmanager

    Start logging bundles

Now you should be able to see your log statements in the configured “example.log” file.

Step 4: Changing the configuration

If you want to change the configuration in the “org.ops4j.pax.logging.properties”, simply restart the PAX Configmanager in the OSGI console:

stop org.ops4j.pax.configmanager
start org.ops4j.pax.configmanager

Happy Logging!

Maven Tycho uses old JAR files

2012/12/22

During the development of SrcMixins4J I faced a strange problem with Tycho: I updated one of the libraries (srcmixins4j-core.jar) without incrementing the version number. I know this is not the standard “-SNAPSHOT” way, but I never had a problem with this before. Maven can handle such updates easily. Inside Eclipse everything was fine, but building with Maven outside Eclipse still referenced the old version and I got compile errors.

It took me some time to figure out that Tycho stores a second copy of the referenced JARs in the Maven repository. There is a folder named “p2/osgi/bundle”.

After deleting the “p2/osgi/bundle/org.fuin.srcmixins4j.core” folder, Tycho finally loaded the new version.

Service-Oriented UI

2012/08/27

In large software development projects, service-oriented architecture is very common because it provides a functional interface that can be used by different teams or departments. The same principles should be applied when creating user interfaces.

In the case of a large company that has, among others, a billing department and a customer management department, an organizational chart might look like this:

Large company

If the billing department wants to develop a new dialog for creating invoices, it might look like this:

As you can see, the screen above references a customer in the upper part. Clicking the “..” button right behind the short name text field will open the below dialog that allows the user to select the customer:

After pressing “Select” the customer data is shown in the invoice form.

It’s also possible to select a customer by simply entering a customer number or typing a short name into the text fields on the invoice screen. If a unique short name is entered, no selection dialog appears at all. Instead, the customer data is displayed directly. Only an ambiguous short name results in opening the customer selection screen.

The customer functionality will be provided by developers who belong to the customer management team. A typical approach involves the customer management development team providing some services while the billing department developers create the user interface and call these services.

However, this approach involves a stronger coupling between these two distinct departments than is actually necessary. The invoice only needs a unique ID for referencing the customer data. Developers creating the invoice dialog don’t really want to know how the customer data is queried or what services are used in the background to obtain that information.

The customer management developers should provide the complete part of the UI that displays the customer ID and handles the selection of the customer:

Using JSF 2, this is easy to achieve with composite components. The logical interface between the customer management department and the billing department consists of three parts:

  • Composite component (XHTML)
  • Backing bean for the composite component
  • Listener interface for handling the selection results

Provider (customer management departement)

Composite component:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:composite="http://java.sun.com/jsf/composite"
	xmlns:ice="http://www.icesoft.com/icefaces/component"
	xmlns:ace="http://www.icefaces.org/icefaces/components"
	xmlns:icecore="http://www.icefaces.org/icefaces/core">

<ui:composition>

	<composite:interface name="customerSelectionPanel" displayName="Customer Selection Panel" 
	                     shortDescription="Select a customer using it's number or short name">
		<composite:attribute name="model" type="org.fuin.examples.soui.view.CustomerSelectionBean" required="true" />		
	</composite:interface>

	<composite:implementation>
	
		<ui:param name="model" value="#{cc.attrs.model}"/>
	
		<ice:form id="customerSelectionForm">
			<icecore:singleSubmit submitOnBlur="true" />
			<h:panelGroup id="table" layout="block">

				<table>

					<tr>
						<td><h:outputLabel for="customerNumber"
								value="#{messages.customerNumber}" /></td>
						<td><h:inputText id="customerNumber"
								value="#{model.id}" required="false" /></td>
						<td>&nbsp;</td>
						<td><h:outputLabel for="customerShortName"
								value="#{messages.customerShortName}" /></td>
						<td><h:inputText id="customerShortName"
								value="#{model.shortName}" required="false" /></td>
						<td><h:commandButton action="#{model.select}"
								value="#{messages.select}" /></td>
					</tr>

					<tr>
						<td><h:outputLabel for="customerName"
								value="#{messages.customerName}" /></td>
						<td colspan="5"><h:inputText id="customerName"
								value="#{model.name}" readonly="true" /></td>
					</tr>

				</table>

			</h:panelGroup>
		</ice:form>

	</composite:implementation>

</ui:composition>

</html>

Backing bean for the composite component:

package org.fuin.examples.soui.view;

import java.io.Serializable;

import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import javax.inject.Named;

import org.apache.commons.lang.ObjectUtils;
import org.fuin.examples.soui.model.Customer;
import org.fuin.examples.soui.services.CustomerService;
import org.fuin.examples.soui.services.CustomerShortNameNotUniqueException;
import org.fuin.examples.soui.services.UnknownCustomerException;

@Named
@Dependent
public class CustomerSelectionBean implements Serializable {

	private static final long serialVersionUID = 1L;

	private Long id;

	private String shortName;

	private String name;

	private CustomerSelectionListener listener;

	@Inject
	private CustomerService service;

	public CustomerSelectionBean() {
		super();
		listener = new DefaultCustomerSelectionListener();
	}

	public Long getId() {
		return id;
	}

	public void setId(final Long id) {
		if (ObjectUtils.equals(this.id, id)) {
			return;
		}
		if (id == null) {
			clear();
		} else {
			clear();
			this.id = id;
			try {
				final Customer customer = service.findById(this.id);
				changed(customer);
			} catch (final UnknownCustomerException ex) {
				FacesUtils.addErrorMessage(ex.getMessage());
			}
		}
	}

	public String getShortName() {
		return shortName;
	}

	public void setShortName(final String shortNameX) {
		final String shortName = (shortNameX == "") ? null : shortNameX;
		if (ObjectUtils.equals(this.shortName, shortName)) {
			return;
		}
		if (shortName == null) {
			clear();
		} else {
			if (this.id != null) {
				clear();
			}
			this.shortName = shortName;
			try {
				final Customer customer = service
						.findByShortName(this.shortName);
				changed(customer);
			} catch (final CustomerShortNameNotUniqueException ex) {
				select();
			} catch (final UnknownCustomerException ex) {
				FacesUtils.addErrorMessage(ex.getMessage());
			}
		}
	}

	public String getName() {
		return name;
	}

	public CustomerSelectionListener getConnector() {
		return listener;
	}

	public void select() {
		// TODO Implement...
	}

	public void clear() {
		changed(null);
	}

	private void changed(final Customer customer) {
		if (customer == null) {
			this.id = null;
			this.shortName = null;
			this.name = null;
			listener.customerChanged(null, null);
		} else {
			this.id = customer.getId();
			this.shortName = customer.getShortName();
			this.name = customer.getName();
			listener.customerChanged(this.id, this.name);
		}
	}

	public void setListener(final CustomerSelectionListener listener) {
		if (listener == null) {
			this.listener = new DefaultCustomerSelectionListener();
		} else {
			this.listener = listener;
		}
	}

	public void setCustomerId(final Long id) throws UnknownCustomerException {
		clear();
		if (id != null) {
			clear();
			this.id = id;
			changed(service.findById(this.id));
		}
	}

	private static final class DefaultCustomerSelectionListener implements
			CustomerSelectionListener {

		@Override
		public final void customerChanged(final Long id, final String name) {
			// Do nothing...
		}

	}

}

Listener interface for handling results:

package org.fuin.examples.soui.view;

/**
 * Gets informed if customer selection changed.
 */
public interface CustomerSelectionListener {

	/**
	 * Customer selection changed.
	 *
	 * @param id New unique customer identifier - May be NULL.
	 * @param name New customer name - May be NULL.
	 */
	public void customerChanged(Long id, String name);

}

User (billing departement)

The invoice bean simply uses the customer selection bean by injecting it, and connects to it using the listener interface:

package org.fuin.examples.soui.view;

import java.io.Serializable;

import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.inject.New;
import javax.inject.Inject;
import javax.inject.Named;

@Named("invoiceBean")
@SessionScoped
public class InvoiceBean implements Serializable {

	private static final long serialVersionUID = 1L;

	@Inject @New
	private CustomerSelectionBean customerSelectionBean;

	private Long customerId;

	private String customerName;

	@PostConstruct
	public void init() {
		customerSelectionBean.setListener(new CustomerSelectionListener() {
			@Override
			public final void customerChanged(final Long id, final String name) {
				customerId = id;
				customerName = name;
			}
		});
	}

	public CustomerSelectionBean getCustomerSelectionBean() {
		return customerSelectionBean;
	}

	public String getCustomerName() {
		return customerName;
	}

}

Finally, in the invoice XHTML, the composite component is used and linked to the injected backing bean:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:fuin="http://fuin.org/examples/soui/facelets"
      xmlns:customer="http://java.sun.com/jsf/composite/customer">

    <ui:composition template="/WEB-INF/templates/template.xhtml">
        
        <ui:param name="title" value="#{messages.invoiceTitle}" />
    
        <ui:define name="header"></ui:define>
    
        <ui:define name="content">
        	<customer:selection-panel model="#{invoiceBean.customerSelectionBean}" />
        </ui:define>

        <ui:define name="footer"></ui:define>

    </ui:composition>
    
</html>

Summary
In conclusion, parts of the user interface that reference data from other departments should be the responsibility of the department that delivers the data. Any changes in the providing code can then be easily made without any changes to the using code. Another important benefit of this method is the harmonization of the application’s user interface. Controls and panels that display the same data always look the same. Every department can also create a repository of its provided user interface components, making the process of designing a new dialog as easy as putting the right components together.

Strange Maven generics problem

2012/05/06

Today I got this strange error when compiling with Maven:

"type parameters of TYPE cannot be determined; no unique maximal instance exists for type variable TYPE with upper bounds TYPE,java.lang.Object"

After googling around I found this solution described by Sarath Chandra.

Interfaces with default implementation – Mixins with AspectJ

2012/02/07

Some weeks ago, I implemented several classes for the CQRS Meta Model. I found myself repeating the same code over and over again, as it was not possible to extend the same base class.

Damn… I wished Java had Mixins! After a short look a Qi4j, which seems a bit too heavy for my little use case, I remembered AspectJ’s Inter-type declarations. You can declare members (fields, methods, and constructors) that are owned by other types!

So here we go – Let’s define some behavior:

/**
 * Something that has a comment.
 */
public interface Commentable {

    public void setComment(String comment);

    public String getComment();

}

Now we’re going to create an aspect that provides the default implementation for the above interface:

/**
 * Implements the behavior of an object that has a comment assigned.
 */
public aspect CommentableAspect {

    private String Commentable.comment;

    public final String Commentable.getComment() {
        return this.comment;
    }
    
    public final void Commentable.setComment(final String comment) {
        this.comment = comment;
    }
}

All you have to do now is to implement the interface:

/**
 * Class with a comment field. 
 */
public class TestClass implements Commentable {

    // All methods are already implemented by 
    // simply adding the interface!
    
}

That’s it! All the necessary fields and methods are now added by AspectJ. You can now concentrate on composing behavior instead of thinking about a hierarchy of subclasses.

If you’d like to, it’s also possible to override the provided default methods (Caution: You’d have to remove the “final” from the aspect!) . I personally prefer the Design for Extension principle, and my methods are always abstract, final, or have an empty implementation.


Follow

Get every new post delivered to your Inbox.