Archive

Author Archive

Configuring Maven to use SLF4J

November 6th, 2011 6 comments

I mainly write articles for two reasons: to understand something that is new to me or to document something I regularly have to explain to others. This article definitely falls in the second category: in order to celebrate the new 1.0.0 version of Logback, I’ve decided to write down once and for all how to properly use SLF4J with Maven since it seems there’s no shortage of questions about it.

Basics

The basis of SLF4J is to have two separate components, one API and one implementation. That means that your code should solely be dependent on the API thus the implementation can be changed at your convenience. Remember that decoupling code from implementations by introducing an interface should be your first concern: at the library level, it’s the role of an API.

This is easily done like this in your POM:

<project ...>
	<dependencies>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.6.4</version>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<scope>runtime</scope>
			<version>1.0.0</version>
		</dependency>
	<dependencies>
</project>

The runtime scope prevents us from using Logback’s implementation classes when coding, which achieves decoupling.

Note: if you’re using a parent POM for your project (because you have modules), it goes without saying the above dependencies should be under the dependencyManagement section.

Bridging

Since an application with only logging features is a bit limited, it’s highly likely we’ll need other dependencies. Of course, some of those dependencies may use other logging frameworks, such as Commons Logging or Log4J.

For example, Spring uses Commons Logging: thus, logs produced by our application would use logback while those produced by Spring would use Commons Logging. This strategy needs two different configurations files (as well as knowledge of both) which is not very intuitive. Moreover, this would be unwieldly when reading twothe flow on two different sources. Note that this could be mitigated by using logging targets other than files (which I haven’t seen yet).

Fortunately, SLF4J provides bridging components that let us wire third-party API calls directly to SLF4J. For Spring, that means removing all dependencies to Commons Logging and replacing them with a single dependency to the Commons Logging to SLF4 bridge.

<project ...>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>3.0.0</version>
			<exclusions>
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>3.0.0</version>
			<exclusions>
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>3.0.0</version>
			<exclusions>
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>1.6.2</version>
		</dependency>
	<dependencies>
</project>

Like in the section above, you should preferably use the

Note: although this knowledge is by no means necessary, know that since API and implementation are both packages together in the commons-logging.jar, the jcl-over-slf4.jar bridge completely replaces the API classes provided by Commons Logging. That means you shouldn’t have both JAR in your classpath!

Troubleshooting

Remember the Highlander rule: “there can be only one”. In this case, there can be only one implementation available on the classpath since SLF4J uses the Java Services Provider. If its the case, SLF4J will display a “Multiple bindings were found on the class path” warning and uses the first it finds (first on the classpath). Since classpaths are ordered by Maven, there’s little chance it will be the thing we want. Thus, take care of not putting slf4j-simple in the test scope along with logback or be prepared to face undetermined side-effects.

To go further:

Categories: Java Tags: ,

‘Learning Vaadin’ is out

October 30th, 2011 8 comments

This is it! After 10 monts of work, my first book is out: ‘Learning Vaadin’ is now available at Packt and Amazon.

First things first, what’s is Vaadin? Vaadin is a presentation-layer web framework that let you easily develop Rich Internet Applications. It does so by provding an abstraction over the Servlet API and by letting developers assemble components to design screens (as opposed to pages as in previous generation web frameworks). If you got 5 minutes to spare, you can go try the tutorial and be convinced yourself. Note that I do not hold Vaadin for a golden hammer, but in most contexts, it just is the right tool.

Now, why write a book? An imperative prerequisite is to believe in the subject. For me, it was love at first sight… I already wrote on Vaadin and used it in real pre-sales demos. During a conversation with Joonas Lehtinen, Vaadin’s CEO, he mentioned he had been approached by Pack to write a book on the subject. My brain processed the information and mere minutes later, I proposed myself.

Although writing a book is like coding in a project in many ways: there’s a schedule, limited time, reviewing (testing), rewriting (bug fixing), ups and downs, it has not been easy for me. I’m admirative of people who regularly write books in their spare time. They need discipline, of course, but also a supportive family and the right publisher. Fortunately, I had these assets this time and I’m now proud to have finished the book.

But is it finished? The strangest is that I do not realize yet. I’m waiting to hold a hard-copy in my hands to really think ‘I’ve done it’. Once received, I believe I will be entitled to some much-deserved R&R :-)

‘Learning Vaadin’ in the news:

You’re welcome to mention other references I may have missed.

Categories: JEE Tags:

Simplest Push

October 16th, 2011 4 comments

When I began working more than 10 years ago, I expected push technologies from web (or application) servers. I was very disappointed when I realized that, no, there weren’t such things.

Nowadays, there are many attemps at providing push technologies. They even come from such simple technologies as HTML: aside from WebSockets, I recently learned about Server-Sent Events, another push technology brought by HTML5. Whereas WebSockets aim to provide full-duplex communication, Server-Sent Events (SSE) is just push from server to client. I just had to try it!

Of course, since HTML5 is still in editor’s draft, not all browsers are SSE compatible. This compatibility matrix shows which browser you can use with SSE. Obviously, Internet Explorer is not one of them but apart from it, it’s pretty much your choice (if you’re not mobile).

Now, SSE itself is very simple:

  • Just create an EventSource object in JavaScript on the client-side
  • Send the response with the right MIME type and format

Let’s try it. On the HTML page, we create an EventSource. The onmessage function is called whenever a new event is pushed from the server.

<script type='text/javascript'>
	var source = new EventSource("generate");

	var counter = 0;

	source.onmessage = function(event) {

		var tbody = document.getElementById('numbers').tBodies[0];

		var tr = tbody.insertRow(0);

		var counterTd = tr.insertCell(0);

		counterTd.innerHTML = counter++;

		var randomTd = tr.insertCell(1);

		randomTd.innerHTML = event.data;
	};
</script>

The above snippet will fill-in a two columns table in the page, the first column as an incremental number, the second one as the message received by SSE.

Next is the server-side. Since I’m a Java fan boy, I’ll do it with a servlet but any web technology worth its salt can be used. Notice the MIME type used ("text/event-stream") and the data prefix in the response:

public class RandomNumberServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
			IOException {

		resp.setContentType("text/event-stream");

		Random random = new Random();

		PrintWriter writer = resp.getWriter();

		String next = "data:" + String.valueOf(random.nextInt(100) + 1);

		System.out.println(next);

		writer.write(next);

		writer.flush();
	}
}

Apart from the servlet mechanics and the random number generation, the code simply writes a string in the response writer.

Warning: don’t ever forget the data prefix, else it will be treated as an error on the client-side and your onmessage function won’t be called (lost a good 30 minutes to figure that out).

That’s it folks! With these two snippets, we created the basis for a whole push application, with nothing more than simple code. Now, I wouldn’t recommend using this so long as the specs are in draft but the feature is so simple to implement it has definitely future in my eyes. Yet, the specifications are so small I would consider reading them right away.

As always, you can find here the sources for this project in Maven/Eclipse format, so you can toy with it right away!

Categories: Development Tags:

Maven doesn’t suck, your POM does

October 9th, 2011 2 comments

Maven bashing is an all-time favorite: there are plenty of articles telling how Maven downloads the whole Internet, or how POMs are bloated and so on.

While I agree that Maven could be perfected, I’m also aware that some (if not most) of its shortcomings are not intrinsic but are caused by (very) bad configuration. Worse, even if used correctly in your projects, problems sometimes come from third-party dependencies! You do not believe me? Well, two examples follow, from standard libraries.

Log4J

Coming from the classic logging framework, this may seem a surprise but log4j POM is a mess. Just look at its dependencies section:

<dependencies>
  <dependency>
    <groupId>javax.mail</groupId>
    <artifactId>mail</artifactId>
    <version>1.4</version>
  </dependency>
  <dependency>
    <groupId>javax.jms</groupId>
    <artifactId>jms</artifactId>
    <version>1.1</version>
  </dependency>
  ...
</dependencies>

Interestingly enough, Log4J depends on the Java Mail and JMS API! If you are using your application in an application server, you may be in for a rude surprise as conflicts may arise between your dependencies and the libraries available on the server.

Moreover, while some users may have the need of mail or JMS appenders, this is not the case for all of us. As such, there’s clearly a lack of appropriate modularization in the design of the library. Luckily, the above POM is an excerpt of version 1.2.15. Version 1.2.16 uses the optional tag for those libraries (which breaks transitivity): it addresses our application server use-case but is still a problem for those needing the dependencies as they have to add the dependency manually. See here for a thought or two on optional dependencies.

If we need version 1.2.15, there are basically two solutions.

  • Clean but cumbersome: we have to manually exclude JMS and Mail from each POM using Log4J. Who said software development was fun?
  • Gruesome but effective: if we have a Maven enterprise repository, we correct the POM (i.e. we add optional tags) on the repository.

Jasper reports

The Log4J example was straightforward: just the side-effects of bad modularization. Jasper’s POM has another twist, just look at a typical dependency:

<dependency>
  <groupId>com.lowagie</groupId>
  <artifactId>itext</artifactId>
  <version>[1.02b,)</version>
  <scope>compile</scope>
</dependency>

The version part means the dependency’s version should be between 1.02b included and the latest version. This obviously has two drawbacks:

  • From an architectural point of view, how can the POM provider guarantee there won’t be an API break with the latest version?
  • From a Maven POV, it means Maven will try to download the latest version. In order to do that, it will try to contact repo1… You’re beginning to see the problem? If you’re behing a corporate proxy that isolates you from the Internet, you’re toast.

The POM excerpt comes from version 2.0.4. Starting from version 2.0.5, Jasper’s designers used only single version dependencies.

If you’re stuck with older versions, the only solution here is to replace the POM with a manually crafted one that do not use unboundedversion dependencies on your enterprise repository.

Conclusion

Despite the constant noise on the Internet, Maven is a wonderful tool. Yet, even if I take the utmost care to design my POM, some external dependencies make my life harder. It would be better to stop losing time complaining about the tool and invest this time helping the developers of those dependencies to provide better POMs.

Categories: Java Tags:

Free eBook: Apache Maven 3 Cookbook

October 4th, 2011 No comments

Dear readers,

In order to celebrate the release of Apache Maven 3 Cookbook, Packt Publishing contacted me in order to hold a contest to grab a free copy of the eBook!

To be frank, I haven’t a clue toward organizing a contest so the first three who send me a mail at nicolas at frankel dot ch with the subject “Apache Maven 3 Cookbook” will be sent the eBook for free. Don’t waste your time: on your mark, ready, go!

And thanks Packt for these gifts.

Update[10h20]: Sorry folks, all three eBooks have already been given. Winners will be contacted shortly by a Packt representative. Thanks for participating!

Categories: Book review Tags:

TestNG, FEST et CDI

October 2nd, 2011 No comments

No, those are not ingredients for a new fruit salad recipe. These are just the components I used in one of my pet project: it’ss a Swing application in which I wanted to try out CDI. I ended up with Weld SE, which is the CDI RI from JBoss.

The application was tested alright with TestNG (regular users know about my preference of TestNG over JUnit) save the Swing GUI. A little browsing on the Net convinced me the FEST Swing testing framework was the right solution:

  • It offers a DSL for end-to-end functional testing from GUI.
  • It has an utility class that checks that Swing components methods are called on the Event Dispatch Thread (EDT).
  • It may check calls to System.exit().
  • It has a bunch of verify methods such as requireEnabled(), requireVisible(), requireValue() and many others that depend on the component’s type.

The challenge was to make TestNG, FEST and CDI work together. Luckily, FEST already integrates TestNG in the form of the FestSwingTestngTestCase class. This utility class checks for point 2 above (EDT use rule) and create a “robot” that can simulates events on the GUI.

Fixture

FEST manages GUI interaction through fixtures, wrapper around components that can pilot tests. So, just declare your fixture as a test class attribute that will be set in the setup sequence.

Launch Weld in tests

FEST offers an initialization hook in the form of the onSetup() method, called by FestSwingTestngTestCase. In order to launch Weld at test setup, use the following implementation:

protected void onSetUp() {

	// container if of type WeldContainer. It should be declared as a class attribute in order to be cleanly shutdow in the tear down step
	container = new Weld().initialize();

	MainFrame frame = GuiActionRunner.execute(new GuiQuery<MainFrame>() {

		@Override
		protected MainFrame executeInEDT() throws Throwable {

			return container.instance().select(MainFrame.class).get();
		}
	});

	// window is a test class attribute
	window = new FrameFixture(robot(), frame);

	window.show();
}

This will display the window fixture that will wrap the application’s main window.

Generate screenshots on failure

For GUI testing, test failure messages are not enough. Fortunately, FEST let us generate screenshots when a test fails. Just annotate the test class:

@GUITest
@Listeners(org.fest.swing.testng.listener.ScreenshotOnFailureListener.class)
public abstract class MainFrameTestCase extends FestSwingTestngTestCase {
	...
}

Best practices

Clicking a button on the frame fixture is just a matter of calling the click() method on the fixture, passing the button label as a parameter. During developement, however, I realized it would be better to create a method for each button so that it’s easier for developers to read tests.

Expanding this best practice can lead to functional-like testing:

selectCivility(Civility.MISTER);
enterFirstName("Nicolas");
enterLastName("Frankel");

Conclusion

I was very wary at first of testing the CDI-wired GUI. I thought it would be hard and would be too time-consuming given the expected benefits, I was wrong. Uniting TestNG and CDI is a breeze thanks to FEST. Having written a bunch of tests, I uncovered some nasty bugs. Life is good!

Categories: Java Tags: , ,

Migrating from m2eclipse to m2e

September 25th, 2011 3 comments

Since Indigo, the Maven Ecliple plugin formerly known as m2eclipse became part of Eclipse release (at least in the pure Java release). The name of the plugin also changed from m2eclipse to m2e. This was not the sole change, however:

  • The number of tabs on the POM has shrinked drastically, and the features as well. This will probably be the subject of a later post since I feel quite cheated by the upgrade.
  • The POM configuration has been more integrated with Eclipse build (which can cause unwanted side-effects as I described in my last article).

More importantly, projects that began with m2eclipse can be built in Indigo but no contextual Maven menu is accessible on the project itself (though a contextual menu is available on the POM).

In order to migrate flawlessly and have our contextual menu back, some actions are necessary. They are gruesome because it involves updating by hand Eclipse configuration file.

Warning: at this point, you have the choice to stop reading. If you decide to continue and use the process described below, it’s at your own risk!

The Maven plugin recognizes a project as a Maven one based the .project Eclipse proprietary configuration file. To display it, go to the Project Explorer view, click on the scrolling menu at the top right and choose Customize View. You have to uncheck *.resources: along the .project file , you should see a .classpath file as well as a .settings folder.

  1. In the .project:
    • Replace org.maven.ide.eclipse.maven2Builder by org.eclipse.m2e.core.maven2Builder in the buildSpec section
    • Replace org.maven.ide.eclipse.maven2Nature by org.eclipse.m2e.core.maven2Nature in the natures section
  2. In the .classpath, replace org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER by org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER
  3. Finally, in the .settings folder, rename the org.maven.ide.eclipse.prefs file to org.eclipse.m2e.core.prefs. Contents should be left unchanged.

Now, the contextual menu should appear and work accordingly.

Remember, this is a big hack you should only use with the right parachute (at least a source control management system) since it will hurt you plenty if it fails. For me, it has always worked… yet.

Categories: Java Tags: , ,

Better Maven integration leads to unforeseen consequences (bugs)

September 11th, 2011 7 comments

This week, I was faced with what seemed an near-insuperable problem. I was called by one of my dev: as soon as he upgraded his Eclipse (or more precisely, our own already-configured Eclipse), he couldn’t deploy to Tomcat through WTP. Here are the steps I took to resolve the problem and more general thoughts about upgrading and tooling.

The log displayed a ClassNotFoundException, one involving Spring. So, the first step is to look under the hood. Provided you used the default configuration – to use workspace metadata – it should be located under <WORKSPACE>/.metadata/.plugins/org.eclipse.wst.server.core/tmp<i>/wtpwebapps where WORKSPACE is your workspace location and i is an incremental number beginning with 0 assigned by Eclipse to each virtual application server in WTP. There you should see the applications deployed in Eclipse. When I checked, I realized the application was deployed alright, but found no WEB-INF/lib folder.

I had already experienced such deployment problems: I solved them by first forcing publish (right-click on the server and choose Publish) and if not successful, cleaning (it removes all deployment and starts again from scratch). Well, this didn’t work.

Also, sometimes classes are not deployed because there aren’t there in the first place: compilation doesn’t occur (because of bad code or Eclipse may be playful) and this prevents generating .class files. This didn’t seem like the problem but hell, this was a lead like any other. In order to force compilation, clean the project and check recompile afterwards (or check auto build is on). This didn’t work too…

It happened before that closing the project and reopening it resolved some code-unrelated compilation problems. Closing and restarting Eclipse may yield the same results. I did both to no avail. At this point, I was disappointed because all previous steps should have resolved the problem… yet they hadn’t.

Since the project used Maven (and we had m2eclipse installed), I also checked the Maven Dependencies library was correctly referenced: it was. Just to be sure, I disabled and re-enabled dependencies management. Guess what? Nothing changed.

Desperate, I hopelessly browsed through the POM and the following caught my attention:

<plugin>
 <artifactId>maven-war-plugin</artifactId>
 <configuration>
 <packagingExcludes>WEB-INF/lib/*.jar</packagingExcludes>
 </configuration>
</plugin>

This configuration creates skinny WARs so that libraries are not packaged in the WAR but are in the EAR, provided they are referenced, of course (for the right way to create such WARs, see my post from last week). With a faint gleam of hope, I removed the configuration part and it worked, the libraries were finally deployed.

Yes, dear readers, it seems newer versions of the m2eclipse plugin are able to parse some portions of the POM that were not parsed before and act accordingly. Although this is a good news in general, it means we have to carefully check about potential side-effects of upgrading to those newer versions. Of course, this was stupid to upgrade in the first place but think that sometimes it’s mandatory for a newer project.

However, the problem is much more widespread than m2eclipse. It’s very similar to issues adressed in Andrew Spencer’s post, only more so since if we don’t upgrade, we may have to keep an Eclipse instance for each project, that has to be shared between all team members. Right now, I don’t have any solutions for this problem, apart from changing the code to keep in synch with the tool.

PS : since we still wanted to have skinny WARs, I just moved the configuration part in a profile… which was what was configured in the archetype provided by the support team :-)

Categories: JEE Tags: ,

Skinny WAR done right

September 4th, 2011 2 comments

In a previous post, I wrote about how to create skinny WAR with Maven the DRY way: it was not the DRYier way to do it, as was demonstrated to me this week by my colleague Olivier Chapiteau (credit where credit is due).

His solution is far more elegant; it is reproduced below for reference’s sake.

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    http://maven.apache.org/xsd/maven-4.0.0.xsd">
  ...
  <dependencies>
    <dependency>
      <groupId>ch.frankel.blog.ear-war</groupId>
      <artifactId>war-example</artifactId>
      <version>1.0.0</version>
      <type>war</type>
    </dependency>
    <dependency>
      <groupId>ch.frankel.blog.ear-war</groupId>
      <artifactId>war-example</artifactId>
      <type>pom</type> <!-- Here works the magic -->
      <version>1.0.0</version>
    </dependency>
  </dependencies>
...
</project>

That’s it! The beauty lies in using the WAR’s POM as a dependency as well as the WAR itself: it’s simple, DRY and effective.

Categories: JEE Tags: ,

Enough spam

August 28th, 2011 2 comments

Spams are a blogger worst enemy. For me, things went worse gradually, until last month, when I had to face about 10 spam comments per day on average, even though I had the WP-SpamFree plugin installed. When spams were fewer, this was not a problem since I had to moderate comments beforehand: users saw nothing. On my part, however, that meant some precious time managing comments and with the number of spam raising, I couldn’t do it anymore.

My first reflex was to turn authentication on: you couldn’t post a comment without being a legit user first. This was not really a good thing since I would have to manage users and legit comments would drop since people are not really interested in managing another account. However, relying on an external account provider (like Google, OpenId, or whatever) would adress both issues. The crucial point would be to choose the right third-party provider.

Before I could dive further into the problem, I noticed one plugin I regularly deactivated: the Akismet plugin is included in WordPress distribution since I first use the product. Akismet checks comments against their service: it automatically manages spam, either through a web-service or an API. In order to use Akismet, you had to get a license key first. Aye, there’s the rub! In the past, the key could be given free provided you ran on WordPress.com, which is not my case. I don’t know when but those policies have changed: you can now get a key for hosted WordPress instances if those are personal blogs! In this case, you get to choose the price you pay (between 0 and 120$ per year). To be frank, I paid 0, but since I activated the plugin, it managed all the spams and let through 3 genuine comments. This doesn’t prevent me for paranoicaly sifting through all spams to check if it didn’t mark a real comment as spam but until yet, it has not.

In a month or two, I think I will be confident enough no to check anymore and I will pay for a new licence key: time is money.

Categories: Miscellaneous Tags: