CarPlant not accepting null CarModels

Last Friday I finished a training session at a client of ours. Because I had some time to kill in the hotel I was staying in, I polished the sample application I coded up during the training to post it online for the guys of the training. Usually I try to find a little sample application specific to the client's domain to use during the training. This makes it a bit more lively instead of some of the HelloWorld examples.
This client is a big car brand, that have adopted Spring widely throughout their organization. That's why I created a CarPlant system capable of producing cars. Below you can find a little UML diagram displaying the (rather tiny) domain model and services in the system.
In the application, I'm using various techniques that you might not have seen that much yet. Here's a small list of what you can expect:
- @Required dependencies - by using the RequiredAnnotationBeanPostProcessor we can check if certain dependencies are actually set. This mechanism (of course only available on Java 5) is a very nice alternative for the dependency-check attribute in XML
- @NotNull argument checking - this is a simple aspect that I'm usually showing during training sessions. It uses a pointcut driven by annotations (which I think is a very neat way of driving your pointcuts) to check for null arguments passed to methods (so now you know what the title refers to
) - DAOs with and without the use of HibernateTemplate - to show the flexibility of Spring's DAO facilities
- Annotation-driven transaction management which is a feature I definitely recommend if you're on Java 5. Using annotations for transaction management is a very good fit IMO
- Some integration testing - this Spring gem (I don't think I'm the only one with this opinion
) is not used enough yet when I visit clients so let's do a little more promotion of the AbstractTransactionalDataSourceSpringContextTests (thanks Rod for the name
)
The sample uses Maven, so you have to have that installed, because I haven't included the dependencies.

The source code for the sample: CarPlant.zip
Modified

pkmk says:
Added on March 12th, 2007 at 6:37 amfile not found
Corné Kloppers says:
Added on March 12th, 2007 at 7:28 amHi
I get the error below when trying to download the CarPlant.zip file:
Kind regards,
Corné Kloppers
Mobile 27 84 913 0391
http://www.linkedin.com/in/corne
Fax 27 865 03 03 70
Postal P.O. Box 1809, Cape Town, 8000
Error:
======
Error 404 - Not Found
error
You have tried to access something that doesn't exist. It may have been moved or you may have been directed here in error.
You can search the website here, or return to the front page and try again.
Ray says:
Added on March 12th, 2007 at 8:10 amYes, Alef, CarPlant.zip does not exist.
I was looking forward to that sample too
Alef Arendsen (blog author) says:
Added on March 12th, 2007 at 8:13 amAh, sorry about that. I've just fixed it. You should be able to download this now.
Chris Smith says:
Added on March 14th, 2007 at 5:38 pmThanks, Alef, I learned a couple of neat things from this example, for example the convention for locating custom PropertyEditors.
Alef Arendsen (blog author) says:
Added on March 14th, 2007 at 6:02 pmThanks Chris, that's good to hear.
Yes, this convention is something I didn't know about either until a few months ago when Ben Alex pointed it out to me.
glad you liked it.
cheers,
Alef
Stéphane Van Espen says:
Added on September 6th, 2007 at 5:31 am[quote post="137"]@NotNull argument checking - this is a simple aspect that I'm usually showing during training sessions. It uses a pointcut driven by annotations (which I think is a very neat way of driving your pointcuts) to check for null arguments passed to methods (so now you know what the title refers to
)[/quote]
Using Annotations and AOP is a very interesting approach in order to extend the language. But I have some troubles with this approach anyway:
* In this example, if I want to take advantage of this annotation, I HAVE to use Spring every time and everywhere I need to access my objects, because they need to be advised by Spring. If not, the @NotNull will be useless.
* Another problem is that AOP breaks equals() method: myObject.equals(Advised(myObject)) will be true while Advised(myObject).equals(myObject) will be false. This is very annoying because, again, I have to guarantee that Spring will be used everywhere to create my objects. But can I guarantee that ?
What if I use JPA/Hibernate in order to persist my data ? Mapping files demand a concrete class (thus, a non-advised)..unless I can define a factory method ?
Did I miss something ?
Thanks for your help !
Alef Arendsen says:
Added on September 6th, 2007 at 7:50 amHi Stéphane,
as for your first question, yes, you would have to use Spring. It's your own choice as to how negative a side effect you think that is. To my mind it's just as negative a side effect as having to use a JVM to run Java-based programs and just as negative a side effect as having to use Spring (or EJB3) for that matter to use @Transactional to demarcate your transactions. Again, it's up to you to decide what your feeling about this is, I won't force you
.
I don't fully understand the equals() issue. I don't consider this to be a big problem. Spring AOP is designed to apply behavior to services (DAOs, repositories, business services, et cetera) and I don't consider equals methods in those objects to be of real importance. You do have a point about the factory methods and domain objects and their respective equals methods. The recommended approach here would be to start using AspectJ, which removed any of the drawbacks that Advised (i.e. a proxy-based approach) has.
I hope this helps. Please don't hesitate to drop by again and ask for more clarification.
regards,
Alef
Stéphane Van Espen says:
Added on September 6th, 2007 at 9:25 amHello Alef,
Thank you very much for your quick response.
After further thoughts, this is the Proxy-based approach that is annoying me. It makes Spring slightly more intrusive because I need it systematically to create new object instances and I have to implement ApplicationContextAware more often. Now, is it really annoying ? No, the added value of using Spring is certainly much greater…
I see two main drawbacks with the proxy-based approach:
How can I be sure I can use Spring every where ? In the case of JPA, I'm not sure I can…
The equals() contract is broken (a.equals(b) but !b.equals(a)). In a nutshell, the equals() method implemented by the advised object makes an unadvised object (with exactly the same values and same underlying class) different (in my example, 'a' is the unadvised object and 'b' is my advised object). In the case of the @NotNull, that's a pity.
As you suggest, using AspectJ and its bytecode-manipulation capabilities could solve that.
Ah, I feel you want to do a second @NotNull with this approach
Regards,
Stéphane.