It was called XML hell. More precisely XML configuration hell. You would spend hours and days fighting with XML configurations that grew in size and complexity until they became a nightmare.
They call it Annotation hell. It is what happens when you get a the same problems as you had in XML hell manifesting in Annotations. The earliest mention of Annotation hell I can find is from 2004 in James Strachan's old weblog where he uses the term "annotation overkill" but is wrongly quoted in other blogs as saying "annotation hell".
There is an Annotation hell. And I've seen it. A good example is here in Eric Redmond's blog Annotation Hell where he posts a method with 10 annotations on one method operating in at least four contexts.
I've seen this before... although admittedly not nearly as bad... and I have called the same thing "Annotation Buildup" it's the cruft you get on a class that you are annotating for too many simultaneous execution contexts. It is a symptom of a design philosophy flaw.
The annotation centric design directly reverses the problem of XML hell by merging everything back into the class. This is good. It centralizes information related to the class into one place. The flaw is that all the configuration piles up in the same places and it isn't clear how the annotations make sense.
Grails solves this problem using Convention over Configuration (CoC) and a GORM Mapping DSL the effect is a much cleaner looking class. GORM can use the JPA if configured properly. And this isn't a bad combination to work in but the real advantage is being able to both centralize configurations for a class and also group them by context.
Convention keeps configuration hell at bay whether it is created by XML or annotations. Allowing a configuration DSL allows you to keep the flexibility of configurations without the XML and by placing the DSL inside the class definition you can keep everything related to a class together. The DSL also have the advantage of keeping related configurations grouped together so that you don't have to stare at a pile of annotations that don't relate to each other.
CoC in combination with in class DSL for configuration can keep annotation buildup at bay and keep away XML and annotation hell.
Showing posts with label Annotations. Show all posts
Showing posts with label Annotations. Show all posts
2008-11-12
2007-11-14
Groovy Grails and the JPA
If you are using Grails 0.6 or later chances are the tutorials you've found for making EJB3 persistence annotated POJOs work with Grails don't match up exactly. If you're like me, probably need to be made aware of a few differences in configuration. They aren't big... but the little differences could trip you up.
First note my version of myApp/grails-app/conf/DataSource.groovy
Is not the same. Just because configClass = GrailsAnnotationConfiguration.class is set and your IDE says the class is found in this context doesn't mean that it's working for you... that import above still has to happen...
Next, I have added a file under "grails-app/conf/hibernate/hibernate.cfg.xml" and this part goes pretty much like the tutorials from last year... you register each class here one at a time. I need to research this one but I think grails mixes in this hibernate.cfg.xml with another one at run time so just stick to registering your classes. I tried to get fancy here and it didn't work out too well. My working hibernate.cfg.xml looks something like this:
You'll need your Java files to be in "src/java" and annotated up. I will be trying to make a shared JAR file full of only the shared domain objects for the various projects that need them. I don't know how well this is going to work but my idea is to create one set of JPA annotated EJB3 Entity classes and put them in a JAR and share them between various Spring applications. I don't know if that's a good idea or not...
Finally, you'll need to get the compiled class files for these annotated POJOs into "web-app/WEB-INF/classes" that means you need to do a "grails run-app" or similar first so that the Java files get compiled into classes and dropped into the "web-app/WEB-INF/classes" directory.
Once that is done you can run the "grails generate-all" command on your Java classes.
If you're interested in working through the EJB3 examples I have posted ejb3_grails.zip which uses this tutorial by Jason Rudolph but also uses Grails version 1.0_RC1 and the Groovy Eclipse Plugin.
EDIT: in version 1.0 and higher recent experience shows that if you set the Eclipse Groovy plugin to output to bin and set the build path of the Java compiler to output to project/bin class resolution will work fine for the IDE. When Grails itself goes to run the application or build the WAR file, the right class files will make it into "WEB-INF/classes" since Grails uses a separate class cache anyhow. It seems the reason I advised to output Groovy and Java classes to "web-app/WEB-INF/classes" is no longer true.
First note my version of myApp/grails-app/conf/DataSource.groovy
import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration
dataSource {
configClass = GrailsAnnotationConfiguration.class
pooled = true
dbCreate = "create-drop"
driverClassName = "com.mysql.jdbc.Driver"
dialect= org.hibernate.dialect.MySQLInnoDBDialect
url = "jdbc:mysql://localhost:3306/grails"
username = "grails"
password = "grails"
}
Is not the same. Just because configClass = GrailsAnnotationConfiguration.class is set and your IDE says the class is found in this context doesn't mean that it's working for you... that import above still has to happen...
Next, I have added a file under "grails-app/conf/hibernate/hibernate.cfg.xml" and this part goes pretty much like the tutorials from last year... you register each class here one at a time. I need to research this one but I think grails mixes in this hibernate.cfg.xml with another one at run time so just stick to registering your classes. I tried to get fancy here and it didn't work out too well. My working hibernate.cfg.xml looks something like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<mapping package="com.mycompany.shared.domain" />
<mapping class="com.mycompany.shared.domain.Subject" />
</session-factory>
</hibernate-configuration>
You'll need your Java files to be in "src/java" and annotated up. I will be trying to make a shared JAR file full of only the shared domain objects for the various projects that need them. I don't know how well this is going to work but my idea is to create one set of JPA annotated EJB3 Entity classes and put them in a JAR and share them between various Spring applications. I don't know if that's a good idea or not...
Finally, you'll need to get the compiled class files for these annotated POJOs into "web-app/WEB-INF/classes" that means you need to do a "grails run-app" or similar first so that the Java files get compiled into classes and dropped into the "web-app/WEB-INF/classes" directory.
Once that is done you can run the "grails generate-all" command on your Java classes.
If you're interested in working through the EJB3 examples I have posted ejb3_grails.zip which uses this tutorial by Jason Rudolph but also uses Grails version 1.0_RC1 and the Groovy Eclipse Plugin.
EDIT: in version 1.0 and higher recent experience shows that if you set the Eclipse Groovy plugin to output to bin and set the build path of the Java compiler to output to project/bin class resolution will work fine for the IDE. When Grails itself goes to run the application or build the WAR file, the right class files will make it into "WEB-INF/classes" since Grails uses a separate class cache anyhow. It seems the reason I advised to output Groovy and Java classes to "web-app/WEB-INF/classes" is no longer true.
2007-09-12
EJB3 security annotations
So with EJB3 declarative security annotations I can do things like this:
Which will allow me to lift the Frobnicator bean out and drop it into a JUnit tests as a POJO. The POJO can then call the methods in Frobnicator without authentication. This helps doing unit tests and getting higher code coverage. But... isn't the authentication part of what I've written? Isn't that something that needs testing?
So my predicament is how do I provide automated acceptance testing for all the permutations of roles in the system?
@DeclareRoles("ADMIN", "USER")
public class Frobnicator {
@RolesAllowed("ADMIN","USER")
public boolean checkFrobnication() { ... }
@RolesAllowed("ADMIN")
public boolean fullyFrobnicate() { ... }
}
Which will allow me to lift the Frobnicator bean out and drop it into a JUnit tests as a POJO. The POJO can then call the methods in Frobnicator without authentication. This helps doing unit tests and getting higher code coverage. But... isn't the authentication part of what I've written? Isn't that something that needs testing?
So my predicament is how do I provide automated acceptance testing for all the permutations of roles in the system?
Labels:
Annotations,
ejb3,
jaas,
java
2007-06-29
return;
Personally I think that leaving a return statement at the end of a method whether you need one or not lets everyone know you really did mean to end the method there.
In other words, "Yes kids, I did mean to return there, no I didn't nod off and forget to finish the method."
/**
* assign an interview to a person
*
* @param personId
* @param interviewName
*/
@Oneway
@WebMethod(operationName="assign")
public void assign(
@WebParam(name = "personId") String personId,
@WebParam(name = "interviewName") String interviewName
){
InterviewEngine.assign(em, personId, interviewName);
return;
}
In other words, "Yes kids, I did mean to return there, no I didn't nod off and forget to finish the method."
Labels:
Annotations,
code,
java,
soap
2007-01-04
DWR POJO as a front controller for a WebService
In the past I would have written my own JavaScript using XmlHttpRequest and a servlet on the back end. This means I have to maintain a lot of code that has nothing to do with my specific project. I evaluated several Ajax frameworks and settled on DWR for my current project. But I have a problem.
I've been writing a DWR object to act as a front controller to a web service. As I wrote previously when using DWR you write a POJO. Register the POJO in dwr.xml and the annotations take care of the rest. But, what about request scope parameters? The request is gone by the time my POJO is called...
http://getahead.ltd.uk/dwr/server/javaapi
We use the WebContextFactory to pull out context data.
I've been writing a DWR object to act as a front controller to a web service. As I wrote previously when using DWR you write a POJO. Register the POJO in dwr.xml and the annotations take care of the rest. But, what about request scope parameters? The request is gone by the time my POJO is called...
http://getahead.ltd.uk/dwr/server/javaapi
We use the WebContextFactory to pull out context data.
Labels:
Annotations,
API,
DWR2,
Java5,
questions
2007-01-03
@annotations
In case you've been under a rock... Java 5 now has a feature called the annotation and it allows you to attach meta-data to a class or a method. This isn't too terribly exciting unless you write a class that can read these annotations. Official docs here. So what I've found you end up doing is writing a proxy or mediator to handle how the annotated classes are used, what the annotations mean, and how the classes interact.
I'm using DWR at the moment and when we write a POJO and annotate it with the right annotations we get a class that DWR can use to create JSON messages. DWR searches a registered POJO for the "@RemoteMethod" annotations and registers those methods for remote invocation. This is very similar to how the JBossWS system works.
In both DWR and JBWS we are using annotations on POJOs to mark the class and method for consumption by a larger framework that will use the method we wrote to form the unique functional core of an application. We can tell the framework some things about how to consume the method and class using the annotation... and we can use the same POJO in multiple frameworks... in theory.
In theory the same annotations could mean different things to different frameworks. This way a POJO could be fed through a testing tool and then fed to a Web Services framework. The key to using the annotations is that the consuming tool, library, or framework sits across concerns from the POJO.
You POJO should be concerned about one thing, such as how to build an item summary. Your POJO then plugs into the framework. The result is that you program what is unique about your application and forget about everything else.
In designing tools, libraries, or frameworks to consume annotations, consider what is always the same. Write your framework to do those things. Then you register POJO into your framework to do the unique tasks for an application.
I can see a need for about a half dozen annotations frameworks from where I sit. And I can see how a code by convention system could be obsoleted by the astute use of annotations. If the framework is built intelligently, Java 5 could become the fastest and simplest way to build applications because so many concerns could be lifted from the application programmer's shoulders by use of Annotations and well-designed AOP.
I'm using DWR at the moment and when we write a POJO and annotate it with the right annotations we get a class that DWR can use to create JSON messages. DWR searches a registered POJO for the "@RemoteMethod" annotations and registers those methods for remote invocation. This is very similar to how the JBossWS system works.
In both DWR and JBWS we are using annotations on POJOs to mark the class and method for consumption by a larger framework that will use the method we wrote to form the unique functional core of an application. We can tell the framework some things about how to consume the method and class using the annotation... and we can use the same POJO in multiple frameworks... in theory.
In theory the same annotations could mean different things to different frameworks. This way a POJO could be fed through a testing tool and then fed to a Web Services framework. The key to using the annotations is that the consuming tool, library, or framework sits across concerns from the POJO.
You POJO should be concerned about one thing, such as how to build an item summary. Your POJO then plugs into the framework. The result is that you program what is unique about your application and forget about everything else.
In designing tools, libraries, or frameworks to consume annotations, consider what is always the same. Write your framework to do those things. Then you register POJO into your framework to do the unique tasks for an application.
I can see a need for about a half dozen annotations frameworks from where I sit. And I can see how a code by convention system could be obsoleted by the astute use of annotations. If the framework is built intelligently, Java 5 could become the fastest and simplest way to build applications because so many concerns could be lifted from the application programmer's shoulders by use of Annotations and well-designed AOP.
Labels:
Annotations,
Java5,
POJO
Subscribe to:
Posts (Atom)