Archivo de la categoría: Robust Code: best practices

Sometimes I just want to apply to a property exactly the same Bean Validator validations I apply to another property.

Point in case: I have a password property in a User class, and there is a ChangePassword data transfer object somewhere else that happens to have currentPassword, newPassword and repeatPassword fields, used precisely to change User.password.

It is obvious that I will want to apply the validations for User.property to all these fields. And, of course, I want changes to validation rules in the original property to be taken into account, automatically.

Copying them is a no-no, because we will violate the DRY (Don’ Repeat Yourself) rule, and creating a custom validation annotation, say @Password, might be overkill. And it would not convey the right meaning, or that’s how I see it.

Creating some kind of DelegateValidation validator that replicates other validations makes a lot of sense, as it clearly conveys the intention and keeps code DRY.

Here we must get access to the Validator we are using to peform validations to ask it to perform validations against the tracked property. Since I use CDI, as well as the Seam validtor module, I rely on them to inject the right Validator instance in my validator implementation.

However, if you are not using CDI/Seam, or just to make testing easier, I am providing a way to supply a validator via the setGlobalValidator method, that you should call before any validations are performed.

Last but not least, let me tellyou that, if you provide a wrong property name for the validator, the validation will fail with a ValidationException, as attested by some of the following tests.

The tests

For the sake of completeness, here are my tests, written against TestNg:

Here, if there are 5 sessions open when checker is created, and 8 sessions open when dispose is called, you will get an AssertionError, telling you you’ve got 3 extra sessions open you probably forgot to close.

How does it do that?

Now, how does it work? When an instance of SessionAllocationChecker is allocated, it checks the statistics maintained by Hibernate and notes the number of open sessions vs. the number of closed sessions at the moment: the difference will be the number of effectively open sessions at creation time.

If Hibernate statistics are not enabled, it will enable them -and quietly disable them when you call dispose.

Next, when you call getOutstandingSessions or hasOutstandingSessions, it performs the same operation, to check the number of currently open sessions. getOutstandingSessions will return the number of sessions currently open minus the number of session open at creation time, that is, the number of additional sessions you have open and not closed yet.

When you call the dispose method, it ensures Hibernate statistics enabled state is restored to its old status. Besides, it will check whether you have session leakage, by calling getOutstandingSessions , but only if you are executing you app with the JVM -enableassertions option. If that’s the case, an AssertionError exception will be thrown.

If the -enableassertions flag is not set, you will have to check the number of outstanding sessions by calling getOutstandingSessions on you own.

While rough, I found this trick extremely useful: in fact, I use this class to check that I never forget to release sessions/entity managers in my own tests.

Another place where you can put this to good use is in web app filters, to ensure that your requests do not leak sessions.

If you take a look at the code, you will find I have added lots of sanity checks via assertions: using the Hibernate statistics as I do is not completely foolproof, if you clear them or disable them between the moment you created the checker and you disposed it, you will get incoherent readings that will fool SessionAllocationChecker.

While I have provided lots of checks, they are not completely safe -not could they be, given the way statistics are implemented by Hibernate. Keep an open eye, and all will be well.

You’ll have noticed that I use assertions all around: you can read this article if you are interested in knowing why I’m such a fan of assertions.

By the way, if you don’t have at hand a SessionFactory or a EntityManagerFactory to pass it to the SessionAllocationChecker constructor, all is not lost: you can get them from a Session or an EntityManager. How to do it is part of the code: just look at the commented code.

Believe it or not, the code is commented because I just have no tests for it in the library where SessionAllocationChecker belongs.

No test, no public exposure -at least, as part of a high quality library.

From now on, I intend to publish a series on best practices that help create robust code.

It is very important to take into account that these best practices might not be best practices in a different context: techniques that help you write robust code might very well be detrimental to write code at top speed.

So, what’s the context for these “robust code” best practices:

Projects that must run reliably, with almost no downtime.

Projects that need to be able to evolve in a very reliable way.

Public APIs that should remain as stable as possible.

Projects used by very many users.

You will have to keep this in mind to make sense of some of the best practices I’ll write about!