Finally did my SCJP6 exam!

By Rob, May 11, 2010 7:42 pm

Long time no blog, the explanation is here.

After three years of having the good intention, I finally motivated myself to take the SCJP exam. From the moment I started working after my study, I told myself many times that I should for some Java certification. Just to prove that I understand what I’m doing. So I started reading in the SCJP 5 study guide (the Sierra and Bates book), and started several times…..

A lot of information was pretty interesting but on the other hand I couldn’t really motivate myself to learn on exotic facts which I never use in practice. Due that fact, I quit learning on SCJP5. Last year I finally picked it up again by buying the Java 6 version of the Sierra and Bates book. Again fighting with the same contradicting facts of useful and useless knowledge but now determined to finish it!

I’ll give a short summary of how I studied. Started with reading the book and making notes for every chapter. After each chapter, I made the test questions and reviewed them. I added the best practices to the notes and learned from my mistakes which were for 50% just silly and stupid ones. After finishing the book, I never opened it again. From that moment I started practicing by just writing several small test applications to get a feeling with several subjects. And doing different mock tests. I would like to mention and recommend the examlab software from Devaka Cooray, it’s free and is really approaching the real exam.

So that’s it for now. I’m currently working on bookmarkeable ajax urls and back button support for ajax urls in php based on CodeIgniter and JQuery. I’ll definitely post my solution here once it’s a bit finished. And not unimportant, I’m about to leave for a trip to India (for work), maybe I’ll write something about that as well.

Oh but now the most important, the result of my exam:

PASSED with a 85% score!!!

What’s next:

  • Training and collecting for our goal this year
  • Then thinking about another certification
  • Drinking a beer to celebrate my score :)

Tips:

  • Be very secure!! Most of my mistakes were not noticing minor, non-head braking things.
  • Read a good book, make notes, re-read those notes several times
  • Practice as much as you can on mock tests (for example examlab.tk)
  • Visit the Javaranch SCJP forum, contains a lot of useful information
  • Have fun!
Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • DZone
  • RSS
  • Twitter

Filtering your duplicate feedbackmessages in Wicket

By Rob, February 6, 2010 12:11 pm

Last week I noticed that in some of my webapps written in Wicket, messages appear multiple times in a FeedbackPanel (Wicket component). That happens since multiple parts of the same page do different kind of validation which might occur in the same error/warning messages. Not a big problem but duplicate messages look a bit weird to your visitor. It’s easy to fix and probably no rocket science to you but I post it anyway :) .

The solution contains two parts, a custom FeedbackPanel and an implementation of the IFeedbackMessageFilter.

Custom FeedbackPanel:

private class UniqueMessagesFeedbackPanel extends FeedbackPanel
  {
    private UniqueMessageFilter filter = new UniqueMessageFilter();

    @Override
    protected void onBeforeRender()
    {
      super.onBeforeRender();
      // clear old messages
      filter.clearMessages();
    }

    public UniqueMessagesFeedbackPanel(String id)
    {
      super(id);
      setFilter(filter);
    }
  }

And the filter class:

public class UniqueMessageFilter implements IFeedbackMessageFilter
  {
    List<FeedbackMessage> messages = new ArrayList<FeedbackMessage>();

    public void clearMessages()
    {
      messages.clear();
    }

    @Override
    public boolean accept(FeedbackMessage currentMessage)
    {
      // too bad that FeedbackMessage doesnt have an equals implementation
      for(FeedbackMessage message: messages)
        if(message.getMessage().toString().equals(currentMessage.getMessage().toString()))
          return false;
      messages.add(currentMessage);
      return true;
    }
  }

I'm looking for a a more beautiful way to cleanup the messages but it seems impossible since the FeedbackMessage class does not implement an own equals version. And if it was implemented, it propably checks on too much properties, like the component which throws the message and that still results in duplicate messages.

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • DZone
  • RSS
  • Twitter

Context based urls with Apache Wicket

By Rob, January 2, 2010 5:47 pm

It’s been a while that I wrote something technical on my blog. The last ones were mainly about biking which is taking a lot of my spare time these days. I haven’t blogged about Wicket before but that doesn’t mean that I use it a lot. For the last 2 years, I’m using it at my work at Maxxton for developing rich content websites. In one of the usecases a month ago, we needed something for storing parameters in the urls which would never get lost after clicking around. After a little googling on the web, I found an example on the Wicket wiki which allowed you to add the locale in the url. I’ve re-used that example and made it a bit more generic by allowing key-value pairs instead of one hardcoded string.

The used keys are defined by a simple enum:


private enum Param {
LANGUAGE("lan"), THEME("theme");

private final String value;

Param(String value) {
this.value = value;
}

public String getValue() {
return value;
}
};

In this example I used two different params which can be used in combination with eachother or separated. I won’t add all the Java code in long listings over here because of the amount of code but you can download my Eclipse project at the end of this blogpost.

There are actually two important spots, a custom RequestCodingStrategy and the registration of that class in the WebApplication. But before I show that code, let’s give some examples of the urls which will be created/working:

  • http://localhost:8080/urlexample/theme/red/lan/nl/home
  • http://localhost:8080/urlexample/lan/nl/home
  • http://localhost:8080/urlexample/theme/red/home
  • http://localhost:8080/urlexample/home

All of these urls are pointing to the homepage mounted at “home”. The bold parts are the key-value pairs which are read in our RequestCodingStrategy and stored in the session for later use. The beauty of this solution is that every generated url, will still contain these values. So in my example, I created a link to another page called “end” and that url will be something like http://localhost:8080/urlexample/theme/red/lan/nl/end.

So how does that look like, lets start with the 2 overridden methods in my WebApplication:


@Override
protected IRequestCycleProcessor newRequestCycleProcessor() {
return new WebRequestCycleProcessor() {
@Override
protected IRequestCodingStrategy newRequestCodingStrategy() {
return new ParamUrlCodingStrategy(super
.newRequestCodingStrategy());
}
};
}

@Override
public Session newSession(Request request, Response response) {
return new CustomSession(request);
}

The newRequestCycleProcessor() returns the custom RequestCodingStrategy instead of the default one. and the newSession() returns our custom session for storing the values. Nothing special.

Lets take a look now to our custom RequestCodingStrategy where most of the magics happens. I only show a stripped version of the one in the example project:


public class ParamUrlCodingStrategy extends RequestCodingStrategy {

public ParamUrlCodingStrategy(final IRequestCodingStrategy defaultStrategy) {
super(defaultStrategy);
}

@Override
public RequestParameters decode(final Request request) {
final String requestLanguage = getParamValue(request.getPath(),
Param.LANGUAGE);
final String requestTheme = getParamValue(request.getPath(),
Param.THEME);

// for example, use a custom session object to store your values
if (requestLanguage != null) {
((CustomSession) Session.get()).setLanguage(requestLanguage);
}
if (requestTheme != null) {
((CustomSession) Session.get()).setTheme(requestTheme);
}

String url = request.decodeURL(request.getURL());

// remove params from request
for (Param param : Param.values()) {
url = stripParamFromPath(url, param);
}
final String urlWithoutParams = url;

// use decorator for decoding
return getDecoratedStrategy().decode(new RequestDecorator(request) {
@Override
public String getURL() {
return urlWithoutParams;
}

@Override
public String getPath() {
return urlWithoutParams;
}
});
}

@Override
public CharSequence encode(final RequestCycle requestCycle,
final IRequestTarget requestTarget) {
String url = getDecoratedStrategy().encode(requestCycle, requestTarget)
.toString();

// rewrite only requests for pages &amp;amp; links
if (requestTarget instanceof IBookmarkablePageRequestTarget
|| requestTarget instanceof IPageRequestTarget) {

String theme = ((CustomSession) Session.get()).getTheme();
String language = ((CustomSession) Session.get()).getLanguage();

// language
if (language != null &amp;amp;&amp;amp; !language.isEmpty()) {
if (url.startsWith("../")) {
final int lastIndex = url.lastIndexOf("../") + 3;
final String remainingUrl = url.substring(lastIndex);
if (!remainingUrl.isEmpty()) {
url = url.substring(0, lastIndex)
+ Param.LANGUAGE.getValue() + "/" + language
+ "/" + remainingUrl;
}
}
// if starts with . -&gt; skip
else if (!url.startsWith(".")) {
url = Param.LANGUAGE.getValue() + "/" + language + "/"
+ url;
}
}
// and theme
if (theme != null &amp;amp;&amp;amp; !theme.isEmpty()) {
if (url.startsWith("../")) {
final int lastIndex = url.lastIndexOf("../") + 3;
final String remainingUrl = url.substring(lastIndex);
if (!remainingUrl.isEmpty()) {
url = url.substring(0, lastIndex)
+ Param.THEME.getValue() + "/" + theme + "/"
+ remainingUrl;
}
}
// if starts with . -&gt; skip
else if (!url.startsWith(".")) {
url = Param.THEME.getValue() + "/" + theme + "/" + url;
}
}
return url;
}
return url;
}

private String getParamValue(final String path, Param param) {
int index = path.indexOf(param.getValue());
if (index &gt;= 0) {
int indexOfNextSlash = path.indexOf("/", index
+ param.getValue().length() + 1);
String paramValue = path.substring(index
+ param.getValue().length() + 1, indexOfNextSlash);
return paramValue;
}
return null;
}

private String stripParamFromPath(final String path, Param param) {
String paramValue = getParamValue(path, param);

return path.replace(param.getValue() + "/" + paramValue + "/", "");
}

@Override
public IRequestTarget targetForRequest(
final RequestParameters requestParameters) {
// delegate call to decorated codingStrategy, but with params removed
String newPath = requestParameters.getPath();
for (Param param : Param.values()) {
newPath = stripParamFromPath(newPath, param);
}

requestParameters.setPath(newPath);
return super.targetForRequest(requestParameters);
}

@Override
public IRequestTargetUrlCodingStrategy urlCodingStrategyForPath(
final String path) {
String newPath = path;
for (Param param : Param.values()) {
newPath = stripParamFromPath(newPath, param);
}

if (newPath != null &amp;amp;&amp;amp; !newPath.isEmpty()) {
// treat this kind of situation by returning some not null
// codingStrategy,
// to let this kind of request treated by wicket
return new PassThroughUrlCodingStrategy(newPath);
}
return super.urlCodingStrategyForPath(newPath);
}

}

As you can see, the encode() and decode() methods do most of the processing. It’s actually nothing more then adding and removing/reading the parameters. The reason that I liked it, is that it’s always executed, no matter what code is used inside the pages. That’s a secure way of adding parameters and not loosing them and as a little dessert, Google likes them as well! Urls are indexed including state in Google which allows you to create language based urls for example.

So that’s it for now. The post only shows the keyfactors of my example. If you’re more interested, you should download my example project and dive into the code.

Download my example Eclipse project

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • DZone
  • RSS
  • Twitter

NLJug J-Fall 2010

By Rob, November 18, 2009 11:07 pm

Wednesday the 11th of november I visited JFall for the second time. This is the yearly event of the Dutch Java usergroup next to the JSpring in april. I attended on several sessions targetting especially new Java developments. For example the big improvements in JDK 7 where I was interested in.

  • Keynote – Enterprise 2.0: New Technologies, Innovations and Communities (Reginald Hutcherson)
  • Speed up your applications with Java SE 7 (Jeroen Borgers)
  • Scaling Out with Hadoop and NoSql (Age Mooij)
  • Keynote – Adobe Systems (Christophe Coenraets)
  • The Quest for Parallelism: How To ‘upgrade’ Your Application (Jan-Hendrik Kuperus)
  • JDK 7, What’s in it and what’s not (Simon Ritter)
  • Google Wave: what is it, and how does it work? (Jos Dirksen)

(I translated some of the subjects to English)

Three of them had a lot in common, the speeding up, the parallelism and the jdk7 where the most interesting ones. The other sessions where more informative and for fun.

The subjects I was really excited about, are the new concurrency features in Java. Being this more and more important with the current multicore cpus and the cloud computing hype we can’t ignore it! And it’s not only faster, it’s also very cool and not even hard to give it a try as a normal programmer. I even think that this new stuff makes our live easier then the old fashioned threading stuff in Java 5 and earlier (a lot of new stuff in Java 7 is already available through Java 6 in the updates but often not enabled by default).

Some cool and nice features are:

  • Fork join framework (next step in parallelism, helps you execute task based procedures)
  • Escape analysis (improvement in allocating memory for objects based on the scope of the object)
  • Project jigsaw (module management)
  • Compressed 64 bit pointers (store 64 bit pointers in 32 bit)
  • Garbage first collector (new algorithm for garbage collecting)

That’s it for now, I didn’t have the time to start playing around with the new Beta of jdk7. Hope to get started soon!

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • DZone
  • RSS
  • Twitter

Duchenne Heroes 2010

By Rob, November 12, 2009 11:27 pm

This time no technical kind of thing, the last months I’ve been working on an update of a website which I voluntary manage for my athletics club (www.av56.nl). I rewrote my simple own MVC framework to the well know CodeIgniter framework. And except that, I’ve been biking quite a lot too. Especially since I bought a road bike (Giant TCR Advanced 2) next to my mountainbike (Cube Reaction).

That biking crazyness has now been changed into a new adventure called Duchenne Heroes. In short some facts:

  • 7 days of mountainbiking
  • 100 km each day
  • 10.000 altimeters
  • 4 countries
  • 4 people per team

And that all with just one main goal, collecting money for the Duchenne foundation. A good description can be read on wikipedia about what Duchenne is. The idea came up after a few beers (always the guilty one :) ) with some friends and since last saturday, our team of four people is a fact! We started creating a website this week but there’s  a lot of work left: clubjegoes.nl

So, keep an eye on our website if you’re interested or even better, donate money to our team. We need 10.000 euro in total. We’re now busy thinking about how to create special sponsor packages. And not unimportant, start training since this is one of the toughest tours in the Benelux.

My next will soon be published, it’s about the Dutch NLJUG day called JFall which I attended last wednesday. It’s a conference of the Dutch Java user group. I’ll briefly describe the subjects I followed and try to dig into them later. Especially the new Java 7 improvements have my attention, awesome new stuff designed for multi core processors and cloud computing!

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • DZone
  • RSS
  • Twitter

Panorama Theme by Themocracy