My blog has moved!

You should automatically be redirected in 6 seconds. If not, visit
http://blogs.i2m.dk/allan
and update your bookmarks.

Showing posts with label Enterprise. Show all posts
Showing posts with label Enterprise. Show all posts

Friday, 24 October 2008

Replacing TopLink Essentials with OpenJPA as my persistence provider

During the development of my latest pet project I decided to go head-on with many of the latest Java Enterprise APIs. One of these was the Java Persistence API (JPA), which I had already used in a handful of projects before. On previous projects the persistence requirements were very simple. I could use JPA out-of-the-box with TopLink Essentials which is the standard set-up for a JPA project in NetBeans/GlassFish. However, for this new pet project of mine I was in need of storing large binary objects (BLOBs). I was shocked to discover that TopLink Essentials doesn't support the Fetching configuration for relationships and properties. Instead it will Fetch.EAGER everything in a relationship and property. This made my application crash hard (OutOfMemoryException) when ever I would query for all entities containing the BLOB. So, I set out to replace the persistence provider. First I looked at Hibernate. I used Hibernate before JPA was released and never had much trouble with it. Unfortunately I found that Hibernate also doesn't support the fetching configuration (in JPA mode). That lead me to OpenJPA which really surprised me. It is well documented, clean, easy to use, and support the fetch configuration. I've now replaced the persistence provider on two projects with OpenJPA and the performance has increased significantly. However, here are a few gotchas that you have to look out for:


  • Auto-generated identity fields must not have a preset value in your JavaBean (hence, this would give you problems:

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id = 0L


    Instead you should write

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;


  • Collections are Fetch.LAZY by default, so if you got an existing using TopLink Essentials, you have to double check that your relations are not throwing LazyInitializationException upon fetching outside the transation.

  • Remember to specify the Fetch depth (openjpa.MaxFetchDepth) in persistence.xml for using the Fetch.EAGER configuration

  • TopLink Essentials compiles named queries when your application is deploy on the application server, OpenJPA on the other hand compiles the named queries upon first usage.

  • When enabling SQL DDL on OpenJPA it doesn't generate foreign key constraints, unlike TopLink Essentials



That's all for now. I'd love to hear about your experiences with OpenJPA or any other persistence provide you find suitable for your need.

Tuesday, 6 May 2008

Yearly conference at the local Danish IT Society branch

Last week I went to the yearly conference for my local Danish IT Society branch. The topic of the conference was Enterprise Architecture. I was a bit unsure about attending as I was expecting some obscure high-level talks that has never seen the light of day. I was pleasantly surprised! All the speakers did a great job and managed to cover the various facets (from theory, to best practice, to practice) of Enterprise Architecture. What especially caught my attention was the excellent governance and organisational re-structuring implemented at NyKredit headed by their CIO (and president of Danish IT Society) Lars Mathiesen (You can read articles about Mathiesen on Computerworld.dk). From a vendor point-of-view the Vice President SOA Strategy, Ivo Totev of Software AG flew in from Germany. Last year I went for another meeting arranged by Danish IT Society with Scrum founder Jeff Sutherland. I wasn't too impressed as there was too much "going-around-the-bush" and not a clear business case for Scrum. Anyways, I didn't know what to expect from Ivo Totev's presesentation. However, I was very impressed with his presentation about the best practices of Enterprise Architecture coupled with anecdotes about what was working and not working with their clients. If you've got interest in Enterprise Architecture, Service-oriented Architecture (SOA), and Business Process Management, I suggest visiting Software AG's customer community at http://communities.softwareag.com/ where you'll interesting resources such as podcasts, blogs, discussion groups and even a freely downloadable PDF version of the book "BPM Basics for Dummies".

Monday, 17 March 2008

Creating timers in EJB3

While the EJB 3.1 expert group is working on the improved timer service using annotations (See New Features in EJB 3.1) I thought that I'd just bring a small entry on using the timer service in EJB 3.

The timer service works by telling the service when it should timeout (i.e. when shall the "alarm" go off). You can add to this by telling it when it should timeout the first time, and how often (in ms) it should timeout after that. You define which methods on the bean that should be invoked upon timeout by annotating them @Timeout. The timer service is initialised by annotating a TimerService object as a @Resource.

Okay, before I show the code, these are the methods that we need:


  • A method for starting the timer

  • A method for stopping the timer

  • One or more listener methods that will be invoked when the timer has timed-out




@Stateless
public class MyTimerBean implements MyTimerLocal {

/** Service used for scheduling tasks. */
@Resource private TimerService timerService;

/**
* Starts the scheduler.
*
* @param startDate
* Start date
* @param interval
* Interval at which the timeout shall repeat
* @param timerName
* Timer to start
*/
public void startTimer(Date startDate, Long interval, String timerName) {
this.timerService.createTimer(startDate, interval, timerName);
}

/**
* Stops a given scheduler.
*
* @param timerName
* Timer to stop
*/
public void stopTimer(String timerName) {
for (Timer timer : (Collection) this.timerService.getTimers()) {
if (timer.getInfo() instanceof String) {
if (((String) timer.getInfo()).equals(timerName)) {
timer.cancel();
return;
}
}
}
}

/**
* {@link Timeout} event handler for generating a report.
*
* @param timer
* Timer that timed out
*/
@Timeout
public void generateReport(Timer timer) {
if (timer.getInfo() instanceof String) {
if (((String) timer.getInfo()).equals("Generate Report")) {
... do some processing ...
}
}
}

/**
* {@link Timeout} event handler for cleaning the cache.
*
* @param timer
* Timer that timed out
*/
@Timeout
public void cleanCache(Timer timer) {
if (timer.getInfo() instanceof String) {
if (((String) timer.getInfo()).equals("Clean Cache")) {
... do some processing ...
}
}
}
}


Right, so we have a method for starting a timer (startTimer). This method needs to be invoked in order to start the timer. This is one of the drawbacks of the TimerService, you cannot tell it to just start when the application is deployed (will be there in EJB3.1). Instead I use a Servlet Context Listener to invoke the startTimer method when the accompaying webapplication is deployed:


public class TimerInitialisationListener implements ServletContextListener {

/** Local interface for {@link MyTimerBean}. */
@EJB private MyTimerLocal myTimer;

/**
* Initialises the timer service.
*
* @param event
* Event that invoked the listener
*/
public void contextInitialized(ServletContextEvent event) {
Calendar now = Calendar.getInstance();
now.set(Calendar.HOUR_OF_DAY, 0);
now.set(Calendar.MINUTE, 0);
now.set(Calendar.SECOND, 0);
int year = now.get(Calendar.YEAR);
int month = now.get(Calendar.MONTH);
int dayOfMonth = now.get(Calendar.DAY_OF_MONTH);
int hourOfDay = now.get(Calendar.HOUR_OF_DAY);
int minute = now.get(Calendar.MINUTE);
Long repeat = 60000L * 60L * 24L;
LogFactory.getLog(TimerInitialisationListener.class).info("Start time: " + now.getTime());
LogFactory.getLog(TimerInitialisationListener.class).info("Repeat every: " + repeat + " ms (" + (repeat / 3600000L) + " hrs)");

myTimer.startTimer(new GregorianCalendar(year, month, dayOfMonth, hourOfDay, minute).getTime(), 60000L * 60L * 24L, "Generate Report");
}

/**
* Context is uninstalled from the servlet container.
*
* @param event
* Event that invoked the listener
*/
public void contextDestroyed(ServletContextEvent event) {
LogFactory.getLog(TimerInitialisationListener.class).info("Stopping timer");
myTimer.stopTimer("Generate Report");
}
}


When you deploy the enterprise application you will see that the timer is set to start at midnight and execute every 86400000 ms (i.e. every 24 hours). What you will notice is that it is only the generateReport method that is executed fully at every timeout as I've put in a check to ensure that it is the correct action being executed. Instead of using a String as the identifier of the Timer you can create create your own custom objects as pass them instead (just remember to make it serializable).

That's all for now. I'll bring another entry when EJB3.1 has been released and the new timer service annotations have been implemented.

On a side note, I've used Quartz before and it's great - I just like to stick to the standards if it can do the job.

Checkout the JavaDocs for the TimerService for more information.

UPDATE: 6. May 2008: Yesterday I was preparing some code using the timer service and I noticed that only the first method annotated with @TimeOut is executed upon timeout. Therefore, use only one @TimeOut method per SessionBean.