Dashboard > People > Uwe Schaefer > Browse Space > News Items for
  codesmell Log In   View a printable version of the current page.  
  News Items for Nov 06, 2008
  2008/11/06
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
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

November 2008
Sun Mon Tue Wed Thu Fri Sat
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30            

Nov 20, 2008
Jun 16, 2008

This site is powered by a free Atlassian Confluence Personal Server License. Evaluate Confluence for your organisation or read more about Confluence licensing here.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.2.9 Build:#527 Sep 07, 2006) - Bug/feature request - Contact Administrators