This actually started as a discussion between myself and a former colleague. He was saying that he was leaning away from annotations. Given that he's the kind of guy who loves all things annotations, I was intrigued as to why.
Turns out in his project there's a common domain object used by a variety of sub projects; which he wanted to reuse. One dev had annotated the class with JAXB annotations to convert the domain model into a XML representation for another sub project. Another dev had annotated it with JPA annotations to obviously persist the model. When my mate came along just wanting to simply use the POJO, all these dependencies came along with it. Which made me realise during his whinge to me (:p), that annotations are really context dependent because of both the compile time and (most times) runtime dependency on the annotation JAR. This highlighted to me one of the best advantages of an XML "descriptor". If it's there, meta data is added (such as persistence information), if not, the code will still actually run on it's own.
"But hey, part of the behaviour is that it is persisted (or whatever)". Which is true, but another way to think about it is that the annotations force the code to act in a certain "layer". For example you don't just throw domain objects at a database. You usually have some code in there that determines what sort of access other parts of the application has. So it's the responsibility of that layer (in this case the Persistence Layer) to provide the mapping detail between the domain model (as a Java class) and the other representation; which probably is a row in a table in a relational database. The same approach can be taken for your View Layer which might aggregate multiple discrete pieces of domain data into something that is consumed by another application. JAXB marshalling can help here.
What my mate suggested was that in the relevant layer (back to Persistence we go) you extend the class and annotate the extension. But I feel this is ugly as to get it to compile you may have to change the access scopes of class attribute. If Foo has a private string, and AnnotatedFoo extends Foo - no string for you. With reflection we can get around this though, which is what most frameworks use anyway. I feel XML descriptors are the better solution. Pull in Foo which is in a JAR that can be used by anybody, then use the class in the way you want adding the extra behaviour through the descriptor mappings. This way Foo can be left context free. Bundle FooJar with DAOJar in a WAR or EAR with descriptor.xml and you're done.
On the flip side there is a perfectly reasonable trade off for using annotations, if you want to sacrifice that portability. An example of this is Spring AOP. You might want to never operate your code outside a Spring container, and thus to gain the benefits of AOP, you can easily use the annotations. That's a trade off I'd be willing to make in my persistence layer for example, but not in my domain model (although I can't think of a reason why you'd need AOP in a domain model).
I'm not anti annotations, but realising that they bind my code to a particular context means that I have to be really careful using them to facilitate other developers who might want to use the POJO in a different context.
Thursday, August 26, 2010
Tuesday, August 24, 2010
Ambigous documentation and my BMT pain
For the project I'm working on I have an EJB that's operating in a Bean Managed Transaction or BMT. One of the beauties of a BMT is that you can extend your transaction timeout to be longer than the default JTA timeout value for long running DB operations. Sometimes you just have to shift a ton of data around with a minimal amount of domain logic and a BMT suits this nicely.
However I feel there is some ambiguity in the UserTransaction setTransactionTimeout method docs that has caused me a lot of grief.
Modify the timeout value that is associated with transactions started by the current thread with the begin method.
This leaves two possibilities in my mind:
The gotcha is that while both are reasonable interpretations of the API docs, only the second works for me (caveat: I've only tested this on Oracle's OC4J as part of Fusion 10G; other app servers may behave differently).
Needless to say that I took the first option then wondered why I was getting timeouts consistent with the transaction timeout being the value of the server's JTA timeout value, not what I set on the transaction (after starting it). So after a lot of digging, and checking that the container was behaving itself and not starting a transaction when it wasn't, and making sure I was getting access to the correct resources, option two hit me like a brick. Flipping two lines of code, and it all worked perfectly.
When dealing with API doc ambiguities, the thought that "hey I'm reading this wrong" doesn't often enter your head until the very end, when there's blood on the desk from the crack in your skull.
Very annoying!
However I feel there is some ambiguity in the UserTransaction setTransactionTimeout method docs that has caused me a lot of grief.
Modify the timeout value that is associated with transactions started by the current thread with the begin method.
This leaves two possibilities in my mind:
- Start a transaction, and set it's timeout.
- Set the timeout for all transactions started by the UT, then begin transactions when you want to.
The gotcha is that while both are reasonable interpretations of the API docs, only the second works for me (caveat: I've only tested this on Oracle's OC4J as part of Fusion 10G; other app servers may behave differently).
Needless to say that I took the first option then wondered why I was getting timeouts consistent with the transaction timeout being the value of the server's JTA timeout value, not what I set on the transaction (after starting it). So after a lot of digging, and checking that the container was behaving itself and not starting a transaction when it wasn't, and making sure I was getting access to the correct resources, option two hit me like a brick. Flipping two lines of code, and it all worked perfectly.
When dealing with API doc ambiguities, the thought that "hey I'm reading this wrong" doesn't often enter your head until the very end, when there's blood on the desk from the crack in your skull.
Very annoying!
Wednesday, August 11, 2010
Which injection framework to use?
A recent debate has arisen among my colleagues about which dependency injection framework to use. Spring Vs Guice. I like the idea of annotations, and making the compiler do all the hard work of type checking. But I don't think that it's the solution to all our problems, as I briefly discussed earlier. I don't see how a purely annotation approach gives us the testing and environment flexibility. For anyone who's done more than a Web App that hangs on the back of Google's App Engine - we know how important that is.
Granted I don't know Guice very well so there may be a way around my reservations with a purely annotation approach.
Either way the needle lies.
Granted I don't know Guice very well so there may be a way around my reservations with a purely annotation approach.
Either way the needle lies.
Wednesday, August 4, 2010
Love that injection
The EJB 3 specification greatly simplified the world of EJBs by borrowing ideas from the Spring camp, the most powerful of which is the idea of POJOs coupled with annotations if you are living in a >= Java 5 world.
I've been playing around with Spring 3 lately, and I'm starting to find the value again in having an XML configuration/deployment descriptor within my EJB work. In all the annotation hype for EJB3, I wonder if we haven't lost sight of the flexibility that text based configuration can bring us in regards to injecting resources into our beans. Sure XML can be tedious but with the amount of great XML tooling available, is that a good reason not to use the XML options? We can get autocomplete, validation and syntax highlighting out of the box. I personally use Eclipse but other IDEs have the capability. Unfortunately we can see the annotation vs XML debate spiral mostly into personal preference. Sure having the configuration for an external resource in the code is great - if it rarely changes. If you have constant change (say on a per environment basis) perhaps a text based approach is better. Text based configuration is perhaps easier for us to create scenarios for our testing.
I've recently had the problem where I've had to change the JDBC driver for a DataSource due to environment issues. The ORM work is done by JPA. The annotation on the EntityManager points to a particular persistence unit. Great, because that's hardly ever going to change. If we do change the persistence unit, it may have an impact on the rest of the codes behaviour so going into the source is worth it. However there are two different persistence unit configurations - one for production (in the container) and the other for unit testing (out of the container). These are configured in the persistence.xml, and the code is oblivious. Just as it should be.
Unfortunately the wheel is reinvented too many times. Are we really doing anything different by the fact that we need configurable code? I admire an engineers ability to solve the problem. That's what we get paid for. Maybe bundle a properties file in the JAR, find it on the classpath (and load it). Maybe there is a property that we can then use to do a JNDI lookup to get a handle/reference to a DataSource. But why would you do that when you have the <resource-ref> tag available to you in the deployment descriptor.
On a technical note, there is an unfortunate pitfall to using deployment descriptor features like a <resource-ref> that can frustrate a developer and make him/her reach for their own custom solution. Say within a bean you have
My current thinking at the moment is about how we can leverage technology like EJB3 and Spring to cleanly and efficiently solve clients needs. The first onus falls on guys like me, the developers to know our material. The second is that if we don't know the answer to a question (for example how can I change the JNDI location of my injected DataSource at build time) then we need to do our homework. I'm just as much guilty as the next guy for failing to do this. Doesn't mean I shouldn't get a rap over the knuckles for it.
I've been playing around with Spring 3 lately, and I'm starting to find the value again in having an XML configuration/deployment descriptor within my EJB work. In all the annotation hype for EJB3, I wonder if we haven't lost sight of the flexibility that text based configuration can bring us in regards to injecting resources into our beans. Sure XML can be tedious but with the amount of great XML tooling available, is that a good reason not to use the XML options? We can get autocomplete, validation and syntax highlighting out of the box. I personally use Eclipse but other IDEs have the capability. Unfortunately we can see the annotation vs XML debate spiral mostly into personal preference. Sure having the configuration for an external resource in the code is great - if it rarely changes. If you have constant change (say on a per environment basis) perhaps a text based approach is better. Text based configuration is perhaps easier for us to create scenarios for our testing.
I've recently had the problem where I've had to change the JDBC driver for a DataSource due to environment issues. The ORM work is done by JPA. The annotation on the EntityManager points to a particular persistence unit. Great, because that's hardly ever going to change. If we do change the persistence unit, it may have an impact on the rest of the codes behaviour so going into the source is worth it. However there are two different persistence unit configurations - one for production (in the container) and the other for unit testing (out of the container). These are configured in the persistence.xml, and the code is oblivious. Just as it should be.
Unfortunately the wheel is reinvented too many times. Are we really doing anything different by the fact that we need configurable code? I admire an engineers ability to solve the problem. That's what we get paid for. Maybe bundle a properties file in the JAR, find it on the classpath (and load it). Maybe there is a property that we can then use to do a JNDI lookup to get a handle/reference to a DataSource. But why would you do that when you have the <resource-ref> tag available to you in the deployment descriptor.
The beauty of course is that ${propertyName} can be substituted in by your build framework. The Ant <expandproperties> filter is great for this. You're also within the spirit of the framework, and hopefully your code is more maintainable, with no custom loading and no lookups. Of course you may have this requirement across multiple beans so you may have to replicate your custom code across those beans. Ugly!! If you're worried about people not being able to trace what's going on, place a comment over the class attribute "This is configured in the deployment descriptor". That of course is a no brainer because good developers always document their code for future readers ;).
<session>
<ejb-name>SomeBean</ejb-name>
<resource-ref>
<res-ref-name>${propertyName}</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<injection-target>
<injection-target-class>org.foo.SomeBean
</injection-target-class>
<injection-target-name>dataSource
</injection-target-name>
</injection-target>
</resource-ref>
</session>
On a technical note, there is an unfortunate pitfall to using deployment descriptor features like a <resource-ref> that can frustrate a developer and make him/her reach for their own custom solution. Say within a bean you have
What you're doing is essentially two things
@Resource(name="jdbc/SomeDS")
private javax.sql.DataSource dataSource;
- Requesting a DataSource object at the JNDI location jdbc/SomeDS
- Requesting that the reference be assigned to the class attribute dataSource
My current thinking at the moment is about how we can leverage technology like EJB3 and Spring to cleanly and efficiently solve clients needs. The first onus falls on guys like me, the developers to know our material. The second is that if we don't know the answer to a question (for example how can I change the JNDI location of my injected DataSource at build time) then we need to do our homework. I'm just as much guilty as the next guy for failing to do this. Doesn't mean I shouldn't get a rap over the knuckles for it.
Subscribe to:
Posts (Atom)