I like Springframework very much and use it in my day to day business as it eases development in many places. A few days ago I started using Hibernate Envers in order to implement a simple auditing solution for a JPA based application. I was faced with the (typical) requirement that the username of the user currently logged in was written into the audit entity. With Envers you would do that using a
org.hibernate.envers.RevisionListener. This is instantiated by the Envers runtime. That listener required access to the
FacesContext (it’s a JSF based application) to get the user principal from the HTTP request. Not a big deal in general! Still I wanted to keep that testable and usable in various environments, so an abstraction was needed and finally something would have to inject that into my listener.
As I said I’m a fan of Spring and this would be the perfect job and eventually one would propose “yeah, let’s do Spring AOP with AspectJ weaving”. As this application was already in production I didn’t want to add that at this time and was seeking for something more simple but still elegant.
Java as of 1.6 has the concept of SPI and ServiceLoader already built-in. I had never used it before. Here it seemed to perfectly match and it did.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
A file named
META-INF/services/at.package.auditing.UserPrincipalProvider would be responsible for registering the provider implementation, it only contains one or multiple class names:
For getting a runtime instance of such a provider I implemented a helper like
1 2 3 4
It is called like