Categories
Java

Eclipse/E4: Problem with Key Bindings

I recently updated one of my E4 applications from Juno to Kepler (V4.3) release. Beside a few things (e.g. adding the HandlerProcessingAddOn to e4xmi configuration) I suddenly lost my customized key bindings. Unfortunately, there was not even a slight hint anywhere in the net why this happened. Most of the web sites were just referring to the afore mentioned add-on. But this didn’t bring back the missing key bindings.

So the only solution was to debug the bootstrap of RCP/E4 and find out where the key bindings disappeared. I noticed very early that my Binding Table was read but didn’t contain the correct key bindings. Although, an earlier breakpoint revealed that they have been read correctly. However, somehow they were removed and replaced by other ones.

Debugging in Eclipse/E4 is quite exhausting escpecially when you try to trace a problem in the bootstrap mechanism. But finally I saw an extension point (a “processor” to be precise) as root cause. This extension just threw away my key bindings. It eventually turned out to be the org.eclipse.ui.workbench plugin which I required in my application. This plugin defines a BindingToModelProcessor that simply throws away all key bindings within the org.eclipse.ui.contexts.dialogAndWindow Binding Context except those tagged with type:user.

That’s the solution. Simple as that. I added the tag to all my key bindings and they were not removed and working again. So be aware when adding org.eclipse.ui.workbench as a dependency plugin to your E4 application. 😉

Categories
Java

Hibernate 4 with JTA Transactions

The following problem occurred when I was migrating from Hibernate 3 to Hibernate 4.2.3. Scrollable result sets were suddenly throwing exceptions:

org.hibernate.exception.GenericJDBCException: could not advance using next()
	at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:54)
	at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
	at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
	at org.hibernate.internal.ScrollableResultsImpl.next(ScrollableResultsImpl.java:121)
...
Caused by: java.sql.SQLException: Operation not allowed after ResultSet closed
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1078)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:975)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:920)
	at com.mysql.jdbc.ResultSetImpl.checkClosed(ResultSetImpl.java:804)
	at com.mysql.jdbc.ResultSetImpl.next(ResultSetImpl.java:6986)
	at org.hibernate.internal.ScrollableResultsImpl.next(ScrollableResultsImpl.java:116)

It turned out after 3 hours of debugging and research that Hibernate’s 4 JTA implementation relies on having a transaction started not via JTA User Transaction but through Hibernate’s own Session object. The correct configuration in such cases is simply to use CMTTransactionFactory as transaction factory class:

1
2
3
4
5
6
7
8
9
10
11
12
13
<hibernate-configuration>
   <session-factory>
      <!-- How to find the Transaction -->
      <property name="hibernate.transaction.factory_class">org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory</property>
 
      <!-- How to produce transaction -->
      <property name="hibernate.transaction.jta.platform">org.hibernate.service.jta.platform.internal.JOTMJtaPlatform</property>
 
      <!-- Session context with JTA -->
      <property name="current_session_context_class">jta</property>
      ...
   </session-factory>
</hibernate-configuration>

As explanation: The error is primarily caused by a bug in JTA implementation within Hibernate (it does not synchronize Hibernate’s with JTA’s transaction object). It occurs mainly when you use the Entity Manager. In above’s exception, a second retrieval was executed within object iteration which caused Hibernate to think that there is no active transaction and hence, close any previous statements. That’s why the Scrollable Result loses its session.

The solution was published first by Koen Serneels. Many thanks!

Categories
Bugzilla for Java Java

Short notice

I am sorry that the desperately awaited version of B4J is still not available. B4J is supposed to add XML-RPC session support which I couldn’t follow up for a long time. However, you can use the current Snapshot version available via Sonatype to benefit from the UTF-8 encoding fix, the Jira session support and integration with CSV/Excel Utility. The Maven coordinates are:

<dependency>
  <groupId>eu.ralph-schuster</groupId>
  <artifactId>b4j</artifactId>
  <version>1.5.0-SNAPSHOT</version>
</dependency>
Categories
CSV Java

CSV/Excel Utility Package V2.6.1 released

The new version 2.6.1 adds some improvements as of character encoding and bean reading and writing. A complete change log is available through the Maven Site.

You can download the new version here or visit the Homepage of the utility where you will find some examples on how to use it.

The Maven coordinates are:

   <dependency>
      <groupid>eu.ralph-schuster</groupid>
      <artifactid>csv</artifactid>
      <version>2.6.1</version>
</dependency>

PS: Version 2.6.0 has been released just two days ago but was already replaced by V2.6.1 because the V2.6.0 TableReader interface had a superfluous method defined.

Categories
Java RS Library

RS Library V1.1.0 released

I had to do some rework for the RS Library. The most important changes are:

  • RSLIB-19 – Improved DAO registration in abstract DaoFactory implementation
  • RSLIB-20 – Upgrade to Hibernate 4
  • RSLIB-22 – Provide modules as OSGI packages
  • RSLIB-23 – Cache Control for DAOs

A complete documentation can be found either through Javadocs or the appropriate module homepages:

The Maven coordinates are:

   <dependency>
      <groupid>eu.ralph-schuster</groupid>
      <artifactid>baselib</artifactid>
      <version>1.1.0</version>
   </dependency>
 
   <dependency>
      <groupid>eu.ralph-schuster</groupid>
      <artifactid>data</artifactid>
      <version>1.1.0</version>
   </dependency>
 
   <dependency>
      <groupid>eu.ralph-schuster</groupid>
      <artifactid>data-hibernate</artifactid>
      <version>1.1.0</version>
   </dependency>
Categories
Java RS Library

Apache ServiceMix, Camel and XSL Transformation

This topic cost me a few hours. It is basically how to achieve XML transformation when your original XML file contains a DTD reference that cannot be resolved from your system.

My DTD reference looked like this:

<!DOCTYPE root-element SYSTEM "../dtd/core.dtd">

and the route was simply:

	<camelContext xmlns="http://camel.apache.org/schema/spring">
		<route>
			<from uri="file:data/inbox"/>
			<to uri="xslt://xslt/transformation.xsl"/>
			<to uri="file:data/outbox"/>
		</route>
	</camelContext>

The Camel transformation was always complaining about the missing DTD because it was looking for it in the filesystem instead of the bundle.

There exist many hints on the net but none of them really helped (e.g. using a CatalogResolver). So I decided to tamper my Camel route and adding a bean inbetween:

	<bean id="dtdTransformer" class="de.example.xslt.DtdTransformer"/>
 
	<camelContext xmlns="http://camel.apache.org/schema/spring">
		<route>
			<from uri="file:data/inbox"/>
			<bean ref="dtdTransformer"/>
			<to uri="xslt://xslt/bundesliga.xsl"/>
			<to uri="file:data/outbox"/>
		</route>
	</camelContext>

This DtdTransformer is a simple class having one method, transform():

	public static final String DOCTYPE_LINE = "<!DOCTYPE root PUBLIC \"-//PRIVATE//RS//EN\" \"###URI###\">";
 
	public String transform(String body) throws Exception {
		URL url = FileFinder.find(getClass(), "dtd/core.dtd");
		if (url != null) {
			body = body.replaceAll("<!DOCTYPE[^>]*>", DOCTYPE_LINE).replaceAll("###URI###", url.toURI().toString());
		}
		return body;
	}

The URI will be replaced by looking up the DTD file at runtime, here by using my FileFinder class. Then it continues with replacing the special marker ###URI### by the real URI from the file found.

Although the solution sounds so simple, it took me quite a while to find out that the DOCTYPE references needs to be a URI and not a file or URL reference.

Categories
CSV Java

CSV/Excel Utility Package 2.5.0 released

The new version 2.5.0 delivers the package for usage in OSGI containers and improves handling of blank lines and calculated cells in an Excel sheet (this code was contributed by Andrej Czapszys). A complete change log is available through the new Maven Site

You can download the new version here or visit the Homepage of the utility where you will find some examples on how to use it.

The Maven coordinates are:

   <dependency>
      <groupid>eu.ralph-schuster</groupid>
      <artifactid>csv</artifactid>
      <version>2.5.0</version>
   </dependency>
Categories
Java RS Library

RS Library 1.0.0 released

Finally it’s done. I decided to release the first version of all those classes that I implemented and collected throughout the last years, the RS Library. A complete documentation can be found either through Javadocs or the appropriate module homepages:

The Maven coordinates are:

   <dependency>
      <groupid>eu.ralph-schuster</groupid>
      <artifactid>$module</artifactid>
      <version>1.0.0</version>
   </dependency>
Categories
Java

Eclipse E4: Using the TranslationService

This post demonstrates how the TranslationService from Eclipse/E4 can be used in real world applications. First, you need the translation files, bundle.properties (minimum) and e.g. bundle_de.properties for your special language:

myapp.key1 = A text.
myapp.key2 = Another text.

Store these files in OSGI-INF/l10n folder of your plugin. This way, the Eclipse/E4 translation service will find it.

Next, I recommend to have a static helper class that will retrieve the translation service from Eclipse/E4 and returns the translated keys. It could look like this:

public class E4Utils {
 
	public static final TranslationService TRANSLATIONS = getTopContext().get(TranslationService.class);
 
	/**
	 * Finds the top Eclipse context.
	 * @return the eclipse context.
	 */
	public static IEclipseContext getTopContext() {
		return E4Workbench.getServiceContext();
 
	}
 
	/**
	 * Translate the given key.
	 * @param key key to translate
	 * @param contributorUri the contributor URI of the translation
	 * @param args variable replacements (will replace {0}, {1},... placeholders)
	 */
	public static String translate(String key, String contributorUri, Object... args) {
		if (key == null) return "";
		if (key.charAt(0) != '%') key = '%'+key;
		String rc = TRANSLATIONS.translate(key, contributorUri);
		if ((args == null) || (args.length == 0)) return rc;
		return MessageFormat.format(rc, args);
	}
}

Thie helper class provides a method translate() which you pass in the key, the contributor URI of your plugin and any additional arguments. This method does a few things for me. It first checks whether the key starts with ‘%’ which is a requirement for the TranslationService. If this ‘%’ is missing, it will be added automatically. Also it will apply the MessageFormat pattern after translation so you can use more sophisticated translation patterns.

The key is very obvious the string that you mentioned in the bundle.properties file. The contributor URI is of form platform:/plugin/symbolicPluginName. The symbolic plugin name can be looked up in the MANIFEST file. To ease the usage of your helper class, create a Plugin class that adds all information required:

public class Plugin {
 
	public static final String SYMBOLIC_NAME = "rc.rcpplugins.e4";
	public static final String CONTRIBUTOR_URI = "platform:/plugin/"+SYMBOLIC_NAME;
 
	/**
	 * Translate the given key.
	 * @param key key to translate
	 * @param args variable replacements (will replace {0}, {1},... placeholders)
	 * @return translated value
	 */
	public static String translate(String key, Object... args) {
		return E4Utils.translate(key, CONTRIBUTOR_URI, args);
	}
}

Now we can use the translation service at any class in our Eclipse/E4 project. e.g:

	button.setToolTipText(Plugin.translate("myapp.key1"));

I implemented this scheme in all my E4 plugins now (with E4Utils as a central helper in a base plugin) and rapidly translated a medium-sized Eclipse/E4 application within a few hours.

PS: I will publish the base helpers soon as Open Source Eclipse/E4 plugins so you can just install them in your Eclipse instance.

Categories
Java Linux

JavaMail: Sending mails fails

Ever stumbled across this?

javax.mail.SendFailedException: Sending failed;
   nested exception is:
      javax.mail.MessagingException: 501 5.0.0 HELO requires domain address

I wasn’t able for a long time to find the solution in the net although many people reported having this problem. The only hint you find is “There was an invalid entry in /etc/hosts”. But noone said exactly what the “invalid entry” was.

I myself found that there was no invalid entry but the configured hostname of the machine (issue “hostname” in a shell) cannot be resolved by DNS. The result is the given error message from the mail server.

What is happening? JavaMail resolves its own hostname by asking for the local hostname. The SMTP protocol requires the sending domain while handshaking. The server will try to resolve the domain by its DNS. If the hostname sent cannot be resolved then the server responds with “HELO requires domain address” as stated above.

I hope that this issue now becomes clearer to all of you.

PS: Solution is make sure your hostname can be resolved by DNS. Fix your hostname if it’s wrong or add the DNS entry.