Dashboard > People > codesmell > Another useless Blog, virtually noone is going to read....
  codesmell Log In   View a printable version of the current page.  
  Another useless Blog, virtually noone is going to read....
Added by Uwe Schaefer, last edited by Uwe Schaefer on Mai 26, 2008  (view change)
Labels: 
(None)

If you happen to like RSS, try this link
Older Entries can be found in the Blog Archive, whereas very old ones (before 2007) are to be found here.

Labels: fun

especially for me, this is very true:

Posted at 20 Nov @ 4:53 PM by Uwe Schaefer | 0 comments
Labels: wicket, java

ahhh. doesn´t wicket offer a great model of programming webpages? isn´t it too easy to do things like this?

add(new ListView("mylist",someList){
  @Override
  protected void populateItem(ListItem item){
    item.add(new PageLink("deleteThisEntry",new DeletePage(item.getModel())));
  }};
});

but wait, PageLink(Page) is deprecated:

/**
 * This constructor is ideal if a Page object was passed in from a previous Page. Construct a
 * link to the Page. Warning: DO NOT use this for constructing links to pages you didn't already
 * have an instance of. This constructor is strongly discouraged for anything other than linking
 * back to the same page.
 * 
 * @param id
 *            See component
 * @param page
 *            The page
 * @deprecated rather than using this class/ constructor, use normal {@link Link links} and call
 *             setResponsePage in their {@link Link#onClick() onClick} methods.
 */
@Deprecated
public PageLink(final String id, final Page<?> page)

why is that? if you look at it, it is very obvious. because it is not lazy. that means that you´re creating a big bunch of pages without needing them and all of them need to be serialized, maybe replicated etc.

it gets worse: when not reusing listitems, you´ll do that on every rendering of the example code!
even more worse, if your fellow programmer did something funny like:

@SomeFunkyAnnotationForInterception
class DeletePage extends WebPage{
 public DeletePage(IModel objectToDelete){
   deleteObject(objectToDelete.getObject());
   setResponsePage(DeletionDonePage.class);
 }
 //...
}

which at least could be a valid usecase.

so please, please, please - with sugar on top - replace

new PageLink(id,new XYPage(...))

by

new Link(id){ 
 public void onClick(){
  setResponsePage(new XYPage(...));
 }
}

in order to create the page only when needed.

Posted at 06 Nov @ 3:54 PM by Uwe Schaefer | 0 comments
Last changed: Nov 06, 2008 22:54 by Uwe Schaefer
Labels: guice, quartz, java

whenever you have any need for cron-like functionality within your java application, Quartz is the obvious chose for quite a long time now.
i did not need much of what quartz had to offer, so i went with a home-grown implementation. why? the fear of having to integrate a good, but feature-rich framework, you really don´t need most of the time.

well, that was a mistake. Quartz offers a very easy and stable API and a bunch of good helper classes, designed after common usecases. but there is one more important quality that every good framework nowadays has to have: it is non-intrusive in regards to creating its objects.

my 'special' case was integration with guice, so that i could use @Inject to implement my jobs. i was pleased to learn that it was as easy as this:

final class GuiceJobFactory implements JobFactory
{
    private final Injector guice;

    @Inject
    public GuiceJobFactory(final Injector guice)
    {
        this.guice = guice;
    }

    @Override
    public Job newJob(final TriggerFiredBundle bundle) throws SchedulerException
    {
        JobDetail jobDetail = bundle.getJobDetail();
        Class jobClass = jobDetail.getJobClass();
        return (Job) guice.getInstance(jobClass);
    }

}

this example class is used to delegate the actual object creation to Guice. this makes Quartz integration a no-brainer, whatever environment you need it in.

all you have to do then is create the Scheduler accordingly:

public class Quartz
{
    private final Scheduler scheduler;

    @Inject
    public Quartz(final SchedulerFactory factory, final GuiceJobFactory jobFactory) throws SchedulerException
    {
        scheduler = factory.getScheduler();
        scheduler.setJobFactory(jobFactory);
        scheduler.start();
    }

    public final Scheduler getScheduler()
    {
        return scheduler;
    }

    public void shutdown()
    {
        try
        {
            scheduler.shutdown();
        }
        catch (SchedulerException e)
        {
	    // ... handle it
        }
    }
}

and bind it all together like:

public class QuartzModule extends AbstractModule
{
    @Override
    protected void configure()
    {
        bind(SchedulerFactory.class).to(StdSchedulerFactory.class).in(Scopes.SINGLETON);
        bind(GuiceJobFactory.class).in(Scopes.SINGLETON);
        bind(Quartz.class).in(Scopes.SINGLETON);
    }
}

what did i learn from that?

frameworks are easy to integrate as long as they do not necessarily claim to manage the lifecycle of (even their own) objects unless absolutely necessary.
want another proof? see Wicket: Application.newSession(...)

Posted at 06 Nov @ 12:22 AM by Uwe Schaefer | 0 comments

Did you ever try to create an instance of a class with a protected constructor from outside its package?
I ran into this need when working with JPA-Entities of which i wanted to know initial field values. (yeah, i know. kind of black magic...)

It is actually easier, than getting protected Fields:

public static <T> T newInstance(final Class<T> c)
    {
        try
        {
            Constructor<T> constructor = c.getDeclaredConstructor(new Class[] {});
            if (constructor != null)
            {
                constructor.setAccessible(true);
                return constructor.newInstance((Object[]) null);
            }
            else
            {
                throw new IllegalArgumentException("Cannot find empty Contructor for class '" + c.getName() + "'");
            }
        }
        catch (SecurityException e)
        {
            throw ExceptionHelper.wrap(e);
        }
        catch (IllegalArgumentException e)
        {
            throw ExceptionHelper.wrap(e);
        }
        catch (InstantiationException e)
        {
            throw ExceptionHelper.wrap(e);
        }
        catch (IllegalAccessException e)
        {
            throw ExceptionHelper.wrap(e);
        }
        catch (InvocationTargetException e)
        {
            throw ExceptionHelper.wrap(e);
        }
        catch (NoSuchMethodException e)
        {
            throw ExceptionHelper.wrap(e);
        }
    }
Posted at 16 Jun @ 7:47 PM by Uwe Schaefer | 0 comments
Last changed: Jun 23, 2008 08:26 by Uwe Schaefer
Labels: wicket, gem, javascript, editor, richtexteditor

Just another Gem from the Wicket-Mailinglist:

[Update: see comments for updated Version]


francisco.treacy wrote:

i thought i'd like to share a simple behaviour for NicEdit
(http://nicedit.com/).

to use it, just download nicedit and modify NICEDIT_JAVASCRIPT and NICEDIT_ICONS accordingly. (i chose to put them together in the same
package). if you download the basic version (without xhtml/ code view), when adding the behaviour pass 'false' into the constructor, in order not
to use the full panel. of course, you can use it with multiple textareas in the same page.

francisco

public class NicEditTextAreaBehavior extends AbstractBehavior {

	private Component<TextArea<String>> textArea;
	private Boolean fullPanel = Boolean.TRUE;
	
	private static final ResourceReference NICEDIT_JAVASCRIPT =
		new JavascriptResourceReference(NicEditTextAreaBehavior.class, "nicEdit.js");
	
	private static final ResourceReference NICEDIT_ICONS = new
ResourceReference(NicEditTextAreaBehavior.class,
		"nicEditorIcons.gif");
	
	public NicEditTextAreaBehavior() {
	}
	
	public NicEditTextAreaBehavior(Boolean fullPanel) {
		this.fullPanel = fullPanel;
	}	
	
	@Override @SuppressWarnings("unchecked")
	public void bind(Component component) {
		this.textArea = component;
		component.setOutputMarkupId(true);
	}
	
	@Override
	public void renderHead(IHeaderResponse response) {
		super.renderHead(response);
		response.renderJavascriptReference(NICEDIT_JAVASCRIPT);
		response.renderOnDomReadyJavascript("new nicEditor({iconsPath : '"+
RequestCycle.get().urlFor(
				NICEDIT_ICONS) +"', fullPanel : "+ fullPanel +"}).panelInstance('"
+ textArea.getMarkupId() + "');");
	}
}
Posted at 15 Jun @ 10:50 AM by Uwe Schaefer | 2 comments
Labels: wicket, gem, anchor

Another Wicket Gem. Obvious but helpful.

import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.model.IModel;

/**
*  @author Thijs Vonk
**/
public class AnchoredBookmarkablePageLink extends BookmarkablePageLink {

 private static final long serialVersionUID = 1L;

 private IModel stringAnchor;

 public AnchoredBookmarkablePageLink(String id, Class pageClass, IModel anchor) {
   super(id, pageClass);
   this.stringAnchor = anchor;
 }

 public AnchoredBookmarkablePageLink(String id, Class pageClass, PageParameters params, IModel anchor) {
   super(id, pageClass, params);
   this.stringAnchor = anchor;
 }

 @Override
 protected CharSequence appendAnchor(ComponentTag tag, CharSequence url) {
   url = url + "#" + stringAnchor.getObject().toString();
   return url;
 }
 
}
Posted at 13 Jun @ 11:16 PM by Uwe Schaefer | 0 comments
Labels: java, exception

Really weird, what Heinz Kabutz digs out of the java language
Read this newsletter to find out, how System.otu.println("foo") can throw a SQLException

His statement on checked and unchecked seems rather incomplete, though:

My personal opinion is that checked exceptions are not as useful as we would hope. For example, the class java.io.IOException has 74 subclasses in Java 6. So whenever you catch IOException, it could have been any one of 74 different error conditions. None of our code would cope with all of them every time we catch IOException.

Posted at 11 Jun @ 8:36 AM by Uwe Schaefer | 1 comment
Labels: exception, java, style

From an Email conversation this evening:

what do you think about it?


For a while, I was "all flame" about Checked exceptions, but then I
read about their limitations (which are why they aren't included in
C#, more about it there :
http://blogs.msdn.com/csharpfaq/archive/2004/03/12/88421.aspx) and
since I wonder what's the best solution.

i was all behind checked exceptions at first too, until some frameworks i used went nuts on them. that´s where i got interested in the 'other' side: don´t use them at all in order not to dictate your user how to handle exceptional behaviour.
that camp, though never really got me.

to me - like most people about software development - this has 80% to do with common sense and 20% with how your belly feels:

the 80% questions are:
1. can your caller reasonably recover from your exception?
2. do you really WANT to FORCE him to handle this?

good example: FileOutputStream throwing FileNotFoundExceptions

the caller needs to know that, needs to take this possibility into account and CAN reasonably recover from that.

lousy example: FileOutputStream.close() throws IOException.

what the hell am i going to do with that one?

the 20% come in when you realize, that your client´s code must be inevitably cluttered with try/catch statements beyond the acceptable because, for example, any method of your DAO can throw EntityNotFound-exceptions :>

that´d be a showstopper for any acceptence

but if in doubt, i try Checked before unchecked, and see if it really gets THAT messy. -> Safety first

Should I follow Bruce Eckel recommendation : no checked exception,
only runtime ones so they don't get in the way ? Some good old days
return codes ? Checked exception ?

i think checked exceptions do have a serious advantage, especially for 'not-that-incredibly-experienced-programmers' that are forced to think of all possible execution paths, they had missed otherwise.
almost noone cares about the exception in:

void foo(int i) throws IllegalArgumentException

until he finally hits it.

Posted at 08 Jun @ 11:23 PM by Uwe Schaefer | 0 comments
Last changed: Jun 07, 2008 11:42 by Uwe Schaefer
Labels: soa, esb, fowler

Here´s a real funny talk of Fowler and Webber about EAI. Didn´t know Martin Fowler can be an entertainer, too

Posted at 07 Jun @ 11:39 AM by Uwe Schaefer | 1 comment
Labels: java, maven, eclipse, plugin

As a happy Q4E User, i did not waste too much time lately on keeping an eye on the other maven-eclipse-integration projects. Now i stumbled upon this wiki page showing a very detailed feature comparison matrix between the usual suspects. One thing that stroke me is, that m2eclipse is proposed at eclipse.org as well as q4e is. Actually the feature-set of m2eclipse is quite impressive and it looks like, their authors have made quite some improvement lately.

Anyone with a detailed experience of a later m2eclipse version?

Posted at 07 Jun @ 11:16 AM by Uwe Schaefer | 0 comments
Last changed: Jun 06, 2008 08:41 by Uwe Schaefer
Labels: wicket, java, tapestry

The article is about Tapestry 4.1, not v5 as mentioned in the title.

Some say, Tapestry can compare with Wicket. And from a certain perspective, they´re obviously right. In case you have not made up your mind yet, this developerworks article might help you. In there is a thorough side-by-side comparison of tapestry against wicket. Their conclusion:

Tapestry and Wicket are popular representatives of the component-based Web frameworks and probably the most exceptional ones from that camp. With their help, it is possible to build applications of any level of complexity.

While Tapestry offers a declarative approach in component specification, Wicket brings pure Java programming with no XML and no annotations. Wicket has a few strong advantages in page versioning and multi-window support. Wicket also has a few more helpful implementations, including breadcrumbs, a feedback panel, and many of the funny stuff found in dynamic HTML, such as tabbed panels and dialogs.

and of course, the usual word of warning, you can find in any tapestry-related publication:

Finally, Tapestry is in a period of transition today. Tapestry V5 promises many enhancements over V4.1, but there is no planned backward-compatibility.

Posted at 03 Jun @ 10:47 PM by Uwe Schaefer | 5 comments
Last changed: Mai 26, 2008 08:05 by Uwe Schaefer
Labels: scrum, xp, book

... if your intereseted in Scrum. I have read quite a few, but this one is different:

  • very, very compact
  • funny to read
  • no fluff
  • no "why it works"

just: "we do it this way, and it worked" and "we did it that way, and it sucked".

A must read, at least for Scrum beginners:

Scrum and XP from the Trenches

Posted at 26 Mai @ 8:05 AM by Uwe Schaefer | 0 comments
Labels: agile, scrum, story

Quite a good talk (Face & Slides) on InfoQ about the (in Scrum speak) Product Owner´s work on agile development.

Watch it

Posted at 24 Mai @ 10:32 AM by Uwe Schaefer | 0 comments
Labels: wicket, ajax, javascript

Here is an interesting interview with three of the wicket committers (or, should i say legends, personal heros ... ) about how Wicket hides the complexity of AJAX-related JavaScript coding from the productive programmer:

Learning JavaScript is not hard, what is hard is learning FireFox JavaScript, IE6 JavaScript, IE7 JavaScript, Opera JavaScript, WebKit JavaScript, etc. The differences are subtle but can cause huge hang ups and are very annoying to Java developers who are used to Java being much more consistent. Another pain point is the lack of a really good JavaScript debugger, which is a tool Java developers take for granted.

and further

Wicket takes care of users having to marshall and unmarshall data between server and browser by working around the problem. Instead of sending data to the client Wicket renders the components on server side and sends the rendered markup. This might not be as efficient, but it sure makes it much easier and faster to develop ajaxified behaviors. For example, if one wants to update a panel that shows user information on the client via Ajax all that is necessary is to tell Wicket that the panel should be updated. There is no marshalling the User object into a JSON representation, and no unmarshalling it on client, neither is there code to manipulate the DOM on the client.

Posted at 22 Mai @ 2:20 PM by Uwe Schaefer | 0 comments
Last changed: Mai 18, 2008 15:34 by Uwe Schaefer
Labels: java, wicket, guice

if there is anyone suffering from

https://issues.apache.org/jira/browse/WICKET-1403

, i added a quick hack to make it possible to restart the server while persisting the application´s state.

not a final solution, but it works for now and makes the development cycle much faster (for me)

The Problem is, that java.lang.reflect.Type is not Serializable right now. The solution was to store it in the Application´s MetaData, which is of course lost when restarting the Application.

What i do here is using XStream in order to 'serialize' the Type to XML, which then can be serialized normally, so that the MetaData-stuff can be dropped.

This is of course not a valid solution to the above problem, as it introduces a dependency to XStream, but it temporarily makes the roundtrip with guice possible.

To anyone using this hack: note that XStream does not necessarily behave consistently on any JVM:
http://xstream.codehaus.org/faq.html#Compatibility.

package org.apache.wicket.guice;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import org.apache.wicket.Application;
import org.apache.wicket.proxy.IProxyTargetLocator;

import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

class GuiceProxyTargetLocator implements IProxyTargetLocator
{
    private static final long serialVersionUID = 1L;

    private final Annotation bindingAnnotation;

    private transient Type type;
    private final String serializedType;

    GuiceProxyTargetLocator(final Type type, final Annotation bindingAnnotation)
    {
        this.type = type;
        final XStream xstream = new XStream(new DomDriver());
        this.serializedType = xstream.toXML(type);
        this.bindingAnnotation = bindingAnnotation;
    }

    public Object locateProxyTarget()
    {
        final GuiceInjectorHolder holder = (GuiceInjectorHolder) Application.get().getMetaData(
                GuiceInjectorHolder.INJECTOR_KEY);

        if (this.type == null)
        {
            final XStream xstream = new XStream(new DomDriver());
            this.type = (Type) xstream.fromXML(this.serializedType);
        }

        // using TypeLiteral to retrieve the key gives us automatic support for
        // Providers and other injectable TypeLiterals
        final Key<?> key;

        if (this.bindingAnnotation == null)
        {
            key = Key.get(TypeLiteral.get(this.type));
        }
        else
        {
            key = Key.get(TypeLiteral.get(this.type), this.bindingAnnotation);
        }
        return holder.getInjector().getInstance(key);
    }
}

Thinking twice, we could get away without special serialization requirements for at least any Type extending Class....
This does not solve all cases, but might help some people already.

package org.apache.wicket.guice;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import org.apache.wicket.Application;
import org.apache.wicket.proxy.IProxyTargetLocator;

import com.google.inject.Key;
import com.google.inject.TypeLiteral;

class GuiceProxyTargetLocator implements IProxyTargetLocator {
    private static final long serialVersionUID = 1L;
    private final Annotation bindingAnnotation;
    private transient Type type;
    private Class serializableType;
    GuiceProxyTargetLocator(final Type type, final Annotation bindingAnnotation) {
        this.type = type;
        if (type instanceof Class) {
            this.serializableType = (Class) type;
        }
        this.bindingAnnotation = bindingAnnotation;
    }
    public Object locateProxyTarget() {
        final GuiceInjectorHolder holder = (GuiceInjectorHolder) Application.get().getMetaData(
                GuiceInjectorHolder.INJECTOR_KEY);
        if (this.type == null) {
            if (this.serializableType != null) {
                this.type = this.serializableType;
            }
            else {
                throw new IllegalStateException("Used a non-Class type for injection, which is not Serializable.");
            }
        }
        // using TypeLiteral to retrieve the key gives us automatic support for
        // Providers and other injectable TypeLiterals
        final Key<?> key;
        if (this.bindingAnnotation == null) {
            key = Key.get(TypeLiteral.get(this.type));
        }
        else {
            key = Key.get(TypeLiteral.get(this.type), this.bindingAnnotation);
        }
        return holder.getInjector().getInstance(key);
    }
}
Posted at 18 Mai @ 10:50 AM by Uwe Schaefer | 0 comments
Labels: wicket, gem, java

thinking twice, ajax-indicators are not at all eye-candy, but useful from an usablity perspective.

/**
 * Adds an AJAX-Indicator to DropDownChoice 
 * @author Eyal Golan
 */
class DropDownChoiceWithAjaxIndicator extends DropDownChoice implements IAjaxIndicatorAware
{
    private static final long serialVersionUID = 1365817942506006686L;
    private final WicketAjaxIndicatorAppender indicatorAppender = new WicketAjaxIndicatorAppender();

    public DropDownChoiceWithAjaxIndicator(final String id, final IModel choices, final IChoiceRenderer renderer,
            final MarkupContainer markupContainer)
    {
        super(id, choices, renderer);
        init(markupContainer);
    }

    public DropDownChoiceWithAjaxIndicator(final String id, final IModel model, final IModel choices,
            final IChoiceRenderer renderer, final MarkupContainer markupContainer)
    {
        super(id, model, choices, renderer);
        init(markupContainer);
    }

    public DropDownChoiceWithAjaxIndicator(final String id, final IModel model, final IModel choices,
            final MarkupContainer markupContainer)
    {
        super(id, model, choices);
        init(markupContainer);
    }

    public DropDownChoiceWithAjaxIndicator(final String id, final IModel model, final List<Serializable> data,
            final IChoiceRenderer renderer, final MarkupContainer markupContainer)
    {
        super(id, model, data, renderer);
        init(markupContainer);
    }

    public DropDownChoiceWithAjaxIndicator(final String id, final IModel model, final List<Serializable> choices,
            final MarkupContainer markupContainer)
    {
        super(id, model, choices);
        init(markupContainer);
    }

    public DropDownChoiceWithAjaxIndicator(final String id, final IModel choices, final MarkupContainer markupContainer)
    {
        super(id, choices);
        init(markupContainer);
    }

    public DropDownChoiceWithAjaxIndicator(final String id, final List<Serializable> data,
            final IChoiceRenderer renderer, final MarkupContainer markupContainer)
    {
        super(id, data, renderer);
        init(markupContainer);
    }

    public DropDownChoiceWithAjaxIndicator(final String id, final List<Serializable> choices,
            final MarkupContainer markupContainer)
    {
        super(id, choices);
        init(markupContainer);
    }

    public DropDownChoiceWithAjaxIndicator(final String id, final MarkupContainer markupContainer)
    {
        super(id);
        init(markupContainer);
    }

    public String getAjaxIndicatorMarkupId()
    {
        return this.indicatorAppender.getMarkupId();
    }

    private void init(final MarkupContainer markupContainer)
    {
        add(this.indicatorAppender);
    }
}
Posted at 11 Mai @ 10:20 PM by Uwe Schaefer | 0 comments

damn. the more i read, the more i find, the more i have to polish, test and copy over

Here is a simple demonstration of how to prevent "Cross-Site Request Forgery"

/**
 * Form that uses a random uuid token in order to prevent nasty people from messing around (also known as cross site request forgery) ;) 
 * @author igor vaynberg 
 */
class SecureForm extends Form
{
    public SecureForm(final String id)
    {
        super(id);
    }
    private static final long serialVersionUID = 1L;
    private static final String TOKEN_NAME = "SECURE_FORM_TOKEN";
    private String token;

    @Override
    protected void onBeforeRender()
    {
        super.onBeforeRender();
        this.token = UUID.randomUUID().toString();
    }

    @Override
    protected void onComponentTagBody(final MarkupStream markupStream, final ComponentTag openTag)
    {
        super.onComponentTagBody(markupStream, openTag);
        getResponse().write("<input type='hidden' name='" + this.TOKEN_NAME + "' value='" + this.token + "'/>");
    }

    @Override
    public boolean process()
    {
        if (!this.token.equals(getRequest().getParameter(this.TOKEN_NAME)))
        {
            throw new IllegalStateException("token mismatch");
        }
        return super.process();
    }
}
Posted at 11 Mai @ 9:48 PM by Uwe Schaefer | 2 comments
Labels: wicket, gem, java

This template for using a Breadcrumb-like Navigation really shows the beauty of stateful pages that separate wicket from those countless template-based frameworks.

/**
 * Provides a list of Breadcrumbs. THIS IS ONLY A TEMPLATE. DO NOT USE UNMODIFIED 
 * @author igor vaynberg 
 */
public abstract class BreadcrumbPage extends Page
{
    private List<BreadcrumbPage> history = new ArrayList<BreadcrumbPage>();

    public BreadcrumbPage()
    {
        add(new ListView("history", new PropertyModel(this, "history"))
        {
            @Override
            protected void populateItem(final ListItem item)
            {
                final Link link = new Link("link", item.getModel())
                {
                    @Override
                    protected void onClick()
                    {
                        getRequestCycle().setResponsePage((BreadcrumbPage) getModelObject());
                    }
                };
                link.add(new Label("title", ((BreadcrumbPage) item.getModelObject()).getTitle()));
            }
        });
    }

    public BreadcrumbPage(final BreadcrumbPage crumb)
    {
        this();
        this.history.add(crumb); // FIXME you´ll want to limit the list´s size
    }

    protected abstract IModel getTitle();
}
Posted at 11 Mai @ 9:13 PM by Uwe Schaefer | 0 comments
Labels: wicket, gem, java

This one is all about id <-> object mapping when using DropDowns:

/**
 * @author igor vaynberg 
 */
public class DropDownIdChoice extends DropDownChoice
{

    public DropDownIdChoice(String id, IModel model, IModel choices, IChoiceRenderer renderer, Class<?> type)
    {
        super(id, model, choices, renderer);
        setType(type);
    }

    @Override
    public String getModelValue()
    {
        final Object id = getModelObject();
        if (id != null)
        {
            return getConverter(getType()).convertToString(id, getLocale());
        }
        else
        {
            return NO_SELECTION_VALUE;
        }
    }
}
Posted at 11 Mai @ 8:51 PM by Uwe Schaefer | 0 comments
Labels: wicket, gem, java

Another little gem:

/**
 * Form that divides submit-events to inital and resubmit. 
 * @author igor vaynberg 
 */
abstract class ResubmitSafeForm extends Form
{
    private boolean submitted;
    private static final long serialVersionUID = 1L;

    public ResubmitSafeForm(final String id)
    {
        super(id);
    }

    public ResubmitSafeForm(final String id, final IModel model)
    {
        super(id, model);
    }

    protected abstract void onInitialSubmit();

    protected abstract void onResubmit();

    protected final void onSubmitted()
    {
        if (!this.submitted)
        {
            onInitialSubmit();
            this.submitted = true;
        }
        else
        {
            onResubmit();
        }
    }
}
Posted at 11 Mai @ 8:01 PM by Uwe Schaefer | 0 comments
Labels: wicket, gem, java

Another very simple, yet incredibly helpful snippet:

/**
 * Simple Link that renders its Model as a textual body
 * @author Al Maw
 */
abstract class TextLink extends Link
{
    public TextLink(final String id, final IModel model)
    {
        super(id, model);
    }

    @Override
    protected void onComponentTagBody(final MarkupStream markupStream, final ComponentTag openTag)
    {

        // Draw anything before the body?
        if (!isLinkEnabled() && (getBeforeDisabledLink() != null))
        {
            getResponse().write(getBeforeDisabledLink());
        }
        replaceComponentTagBody(markupStream, openTag, getModelObjectAsString());

        // Draw anything after the body?
        if (!isLinkEnabled() && (getAfterDisabledLink() != null))
        {
            getResponse().write(getAfterDisabledLink());
        }

    }
}
Posted at 11 Mai @ 7:23 PM by Uwe Schaefer | 0 comments
Last changed: Mai 11, 2008 11:42 by Uwe Schaefer
Labels: resin, glassfish, java, appserver

while this blog happily ran on glassfish v1 for quite some time now, i have to admit switching back to caucho resin. the reason for this is simple: i will be using resin at work soon again, so any detailed experience with glassfish (at least with anything <v3) will be void.

i worked with resin2 for about 8 years and was quite happy with it (apart from being pissed by its failure to implement the standards). looking at resin3 was quite impressive because of its advanced clustering, watchdog and automatic-restart capabilities as well as its embeddability, which makes wicket-development a breeze.

see for yourselves at http://caucho.com

Posted at 11 Mai @ 11:41 AM by Uwe Schaefer | 0 comments
Last changed: Mai 11, 2008 09:20 by Uwe Schaefer
Labels: wicket, gem, java

it happens quite often that, while browsing the Wicket mailing list, i stumble upon gems, that i fail to find or even remember when i could use them.
this really has to stop

the problem is: there is of course no commen theme about these hacks, components, behaviours etc, so it is very hard to find a good name for a project like that.
i thought of wicket-contrib-kitchensink, but maybe i should give it another try.

until then, i´ll grab these gems and republish them here (after maybe adding a few things and polishing a little) just to make sure, that i wont forget them.
here is the first:

How would one implement "hint text" on a text field in Wicket? By hint text
I mean an empty TextField has greyed out text in it to indicate its purpose,
and gets cleared onFocus?)

the answer & code is from mighty igor vaynberg:

/**
 * Adds hint-text to texfield, that will be erased onFocus 
 * @author igor vaynberg 
 */
public class TextFieldHintBehaviour extends AbstractBehavior
{
    private String pseudoUniqueJavascriptVariableName = this.getClass().getSimpleName()
            + String.valueOf(System.nanoTime());

    public TextFieldHintBehaviour(final IModel hintTextModel)
    {
        this.hint = hintTextModel;
    }

    private final IModel hint;
    private Component c;

    private String hintColor = "gray";
    private String textColor = "black";

    @Override
    public void bind(final Component component)
    {
        super.bind(component);
        this.c = component;
        this.c.setOutputMarkupId(true);
    }

    @Override
    public void renderHead(final IHeaderResponse response)
    {
        response.renderOnDomReadyJavascript("var " + this.pseudoUniqueJavascriptVariableName
                + "=document.getElementById('" + this.c.getMarkupId() + "');" + this.pseudoUniqueJavascriptVariableName
                + ".value='" + this.hint.getObject() + "';" + this.pseudoUniqueJavascriptVariableName
                + ".style['color']='" + this.hintColor + "';");
    }

    @Override
    public void onComponentTag(final Component component, final ComponentTag tag)
    {
        super.onComponentTag(component, tag);
        tag.put("onfocus", "if (this.value=='" + this.hint.getObject() + "') {this.value=''; this.style['color']='"
                + this.textColor + ";'}");
    }

    public String getHintColor()
    {
        return this.hintColor;
    }

    public void setHintColor(final String hintColor)
    {
        this.hintColor = hintColor;
    }

    public String getTextColor()
    {
        return this.textColor;
    }

    public void setTextColor(final String textColor)
    {
        this.textColor = textColor;
    }
}
Posted at 11 Mai @ 9:15 AM by Uwe Schaefer | 0 comments
Last changed: Mai 04, 2008 13:50 by Uwe Schaefer

i just released a simple css-menu component for wicket as a preview.

as always, your´re very welcome to send any kind of criticism.

Posted at 04 Mai @ 1:48 PM by Uwe Schaefer | 2 comments

i recently wrote an article on Warp-persist, an excellent framework for integrating JPA with Guice. This article can be found here.

Posted at 29 Apr @ 12:22 AM by Uwe Schaefer | 0 comments
Labels: java, jpa, eclipse

From http://www.eclipse.org/eclipselink/:

The Eclipse Persistence Services Project (EclipseLink) incubator project's goal is to provide an extensible framework that will enable Java developers to interact with relational databases, XML, and Enterprise Information Systems (EIS) in an efficient and productive manor. EclipseLink will focus on supporting leading persistence standards including the Java Persistence API (JPA), Java API for XML Binding (JAXB), Java Connector Architecture (JCA), and Service Data Objects (SDO).

So, there might be a serious JPA implementation competition soon? Let´s have a look.

Posted at 17 Mrz @ 10:34 PM by Uwe Schaefer | 0 comments
Last changed: Mrz 09, 2008 11:23 by Uwe Schaefer
Labels: q4e, eclipse, java, maven

The lovely Q4E-Eclipse plugin has been updated to version 0.5. New and noteworthy can be found here. You can use this update site to install it.

Particularly the new "Analyze Dependencies" View is awesome!

Posted at 09 Mrz @ 11:18 AM by Uwe Schaefer | 0 comments
Last changed: Mrz 08, 2008 23:11 by Uwe Schaefer
Labels: wicket, guice, resin

I filed another guice related issue at Wicket´s Jira https://issues.apache.org/jira/browse/WICKET-1403. Seems, the injection stuff needs some treatment before the ultra-fast-turnaround development environment will come true.

Let´s hope for the best.

Posted at 08 Mrz @ 9:02 PM by Uwe Schaefer | 0 comments
Labels: java, uml, eclipse

If you happen to have the need to draw a few simple, good-looking UML diagrams, your choices are few. Either you turn to something commercial, overly bloated with things you currently don´t need, or you end up with hardly working, crappy looking and hard to work with Java tools. Yes, there is a middle ground, but was not very familiar with it, until i found this gem: Violet UML Editor. It might not be ready yet, but it is:

  • written in Java
  • standalone or eclipse plugin
  • swiftly working
  • extremely intuitive to use
  • produces good looking diagrams in no time

Neat!

Posted at 08 Mrz @ 11:42 AM by Uwe Schaefer | 0 comments
Labels: ruby, rails

Finally, one guy seeing Ruby for what it is: a 'Scripting Language':

The middle ground is really where Ruby belongs, where it flourishes. It's hardly a general-purpose language, so it could never replace Java and company. With that said, it's far easier to write an incremental backup script in Ruby than in Java. And while Ruby may not be suitable for an enterprise level, high-traffic web application, it's certainly up for some tasks within that application.

Original Post

Posted at 29 Jan @ 9:44 PM by Uwe Schaefer | 0 comments
Labels: java, wicket, google, charts

If you do not have a problem sending Data to Google (some have) and you don´t want to create fancy charts for your wicket application yourself, this component can save you a significant amount of time.
Thanks to Daniel Spiewak for sharing this.

Posted at 27 Jan @ 3:35 PM by Uwe Schaefer | 1 comment
Last changed: Jan 26, 2008 09:16 by Uwe Schaefer
Labels: java

If you happen to face the well known hot-deployment issue of OOMs due to a full Permanent Generation, it is likely that you use something, that keeps hold of your Classes, so that the webapp-classloader cannot be GC´d correctly. This is a wellknown but hard to find & fix issue very many configurations suffer from.
The most common answer is: do not use commons-logging, but slf4j instead - which is easy, but a shot in the dark.

Martin sent two links where the problem is explained very well, and JDK6 is used to track it down and solve.
Rather old, but still very valid.

Resources:

Posted at 26 Jan @ 9:14 AM by Uwe Schaefer | 0 comments
Last changed: Jan 27, 2008 14:46 by Uwe Schaefer
Labels: java, reflection, guice

I just wrote a library that (de-)serializes command objects after transmitting over network. Before executing, i´d like to (re-)inject members annotated with Guices @Inject annotation. I did some Reflection before, but never felt the needed to get hold of private fields, which is now essential.
It´s not a big deal, but in case anyone could use this snippet:

// instead of c.getFields(), use:
 Field[] fields = c.getDeclaredFields();
 AccessibleObject.setAccessible(fields, true);

where c ist the class of the Object you want to access. Then you can iterate over and see, if the field has the annotation in question. Simple, yes - but i had to search for it, so you don´t have to.

Posted at 26 Jan @ 8:43 AM by Uwe Schaefer | 0 comments
Last changed: Jan 17, 2008 08:33 by Uwe Schaefer

I use an in-memory HSQL Database in order to test my JPA/Hibernate Application. Common thing. That explains my surprise on the following situation: I have an Entity with a boolean member:

@Entity public class Foo{
 @Id int id;
 boolean bar;
 [..]
}

Everything works as expected up to here. But then, i use a native query like this:

SELECT id,bar FROM Foo f

Imagine the look of my face when i got this in response:

Caused by: org.hibernate.MappingException: No Dialect mapping for JDBC type: 16

while Type 16 is boolean. WTF? After a little digging, the Hibernate-Dialect is found to be incomplete, for it does not know 'how to map booleans in native queries'.
I don´t get it. I cannot be the first guy running into this. Anyway, i´ll file a bug for the hibernate guys (let´s see if they smack me down for that) and wait and see.

Until then, you can easily work around this by using this extension:

public class CustomHSQLDialect extends org.hibernate.dialect.HSQLDialect
{
    public CustomHSQLDialect()
    {
        registerColumnType(Types.BOOLEAN, "boolean");
        registerHibernateType(Types.BOOLEAN, "boolean");
    }
}

and then use this Dialect in you persistence.xml instead of org.hibernate.dialect.HSQLDialect.

Posted at 17 Jan @ 8:31 AM by Uwe Schaefer | 2 comments
Labels: java, cglib, proxy, macosx

I ran into a very interesting problem few days ago, where JDK5 on MacOSX threw an AbstractMethodError, while JDK6 on Windows and Linux didn´t.
First obvious bet was some class that was compiled to JDK6 bytecode. Unfortunately it wasn´t that easy. While using a debugger, the problem got even more weird... The Method in question was called serveral times with the result you´d expect, but the (n+1)th call failed with the above error (on MAC).
What has happened? We use a CGLib-based Proxy mechanism to call to that method, either directly, or through another method of the same class. The problem there is: the Method in question was declared to be final:

public final Object foo(Object)
{
 ...
}
public void bar()
{
 foo(someObject);
}

So a call to foo via bar worked fine, while a direct call (through the CGLib proxy) failed with AbstractMethodError. You could argue, if the final actually should prevent the Proxy from working (I personally don´t think so).
Once again: on JDK6/win and linux, everything went fine.
I did not have the time to test this on a particular version other than the ones used in the above scenario, so this might be a general difference between JDK5 and 6.

So, when using AOP-like stuff or any other CGLib based technique, be very careful to declare methods final when you want to be compatible with JDK5

Posted at 15 Jan @ 8:58 PM by Uwe Schaefer | 0 comments

I found this to be true, especially the bold statement. Unfortunately this is more a JBoss issue than a Hibernate Issue as this problem is very obvious in the SEAM 'community' as well.

Open-source projects in general are a liability but Hibernate specifically has a serious support problem. Unless you pay the organization money you will find their support is terrible. Bug reports and feature requests will get closed with rude remarks. Posts on discussion forums get ignored. General (free) support is very hard to come by.

Anyone considering using Hibernate should realize that 90% of the time it works like a charm, but you waste days fixing problems with the other 10%. This is how they make their money, as do many other open-source projects, by making the product harder to use and charging for support.

The biggest ease-of-use concern with Hibernate are its exception messages. Sometimes you get misleading error messages that point you in the wrong direction. Other times you get messages that are so vague you have no idea what has gone wrong. If you file a RFE asking them to improve error reporting you will get a rude remark and the RFE will be closed promptly. Just my 2 cents.

Whole Article

Posted at 15 Jan @ 8:57 AM by Uwe Schaefer | 0 comments