tag:blogger.com,1999:blog-77022692007-11-08T06:36:45.592-08:00Emil KirschnerEmil Kirschnerhttp://www.blogger.com/profile/12037382448539987423noreply@blogger.comBlogger12125tag:blogger.com,1999:blog-7702269.post-77758660607285206942007-11-03T15:26:00.000-07:002007-11-03T15:57:00.010-07:00The Leopard and Java 6 IssueEverybody in the Java community kept their keyboards busy lately ranting either against the fact that Apple's latest Mac OS X version doesn't include Java 6, or against those ranting against Apple's decision.<br /><br />I can't deny the issue is bugging me, but not because of the same reasons: I don't really care about using the very latest Java 6 APIs or using the nice splash screen or getting a slightly faster startup time. Here is the problem, the way I see it:<br /><br />On one side we've got Microsoft's Vista, which is clearly going to be the future mainstream OS, despite the fact that today most people are unhappy with it. Now, if you search the web to find out about Java and Vista compatibility, you'll find that the version of Java designed to work with Vista is Java 6. Java 5 was reported to have a huge number of serious issues on Vista. Sun did a great job in fixing many of them in <a href="http://java.sun.com/j2se/1.5.0/ReleaseNotes.html">JDK 5.0u13</a>, but one may wonder how many others have not yet been found. To make the story short, if you want to be sure your application works fine with Vista, you better build it with Java 6.<br /><br />On the other hand Leopard doesn't have Java 6 yet - well it has it, but it's in Beta.<br /><br />So if you develop a product in Java and want to target both Mac OS X and Windows clients, you must make two different releases: one that that is Java 6 based, for Windows, and one that is Java 5 based, for Mac OS. This is far from being the end of the world, but it is a little bit annoying.<br /><br />Things would be so much more simple if either Sun would make a good Java 5 release for vista - which might just be the case with 5.0u13 or if Apple would finalize Java 6 for Mac OS X.Emil Kirschnerhttp://www.blogger.com/profile/12037382448539987423noreply@blogger.comtag:blogger.com,1999:blog-7702269.post-1156229705182800822006-08-21T23:51:00.000-07:002006-08-21T23:55:05.190-07:00still alive?Yup, still alive. Unfortunately didn't have time to write much - did have a few subjects, though. Hope to have a little bit more time starting with September.<br /><br />Cheers,<br />Emil.Emil Kirschnerhttp://www.blogger.com/profile/12037382448539987423noreply@blogger.comtag:blogger.com,1999:blog-7702269.post-1146081064843669102006-04-26T12:24:00.000-07:002006-04-26T12:51:04.913-07:00j2ee postings on server sideWhenever I have a minute I try to share some of my j2ee experience on the server side forums. Here are a links to a few threads of general interest I have participated in:<br /><br /><ul><br /><li><a href="http://www.theserverside.com/discussions/thread.tss?thread_id=40015">Http Referer</a> - how to only accept visitors comming from a precise URL<br /><li><a href="http://www.theserverside.com/discussions/thread.tss?thread_id=39970">ejb and servlet container class loader</a> configurations<br /><li><a href="http://www.theserverside.com/discussions/thread.tss?thread_id=39939">websphere startup class</a> resources<br /><li>about <a href="http://www.theserverside.com/discussions/thread.tss?thread_id=39623">statefull session beans</a><br /><li><a href="http://www.theserverside.com/discussions/thread.tss?thread_id=39727">generic algorithms</a> - a more flexible alternative to big switch / case statements<br /><li>the eternal question: <a href="http://www.theserverside.com/discussions/thread.tss?thread_id=39644">when to use j2ee</a>?<br /><li>someone was wondering if they sould use the <a href="http://www.theserverside.com/discussions/thread.tss?thread_id=39466">file system or a database blob to store xml files</a><br /><li>someone else was wondering how to use <a href="http://www.theserverside.com/discussions/thread.tss?thread_id=38689">j2ee transactions with ejb / servlets</a> configuration<br /><li>another person was wondering about the utility of using a <a href="http://www.theserverside.com/discussions/thread.tss?thread_id=36319">data access objects layer in conjunction with a ORM framework in distributed applications</a>.<br /></ul><br /><br />Enjoy.Emil Kirschnerhttp://www.blogger.com/profile/12037382448539987423noreply@blogger.comtag:blogger.com,1999:blog-7702269.post-1140992070871588542006-02-26T14:10:00.000-08:002006-03-25T01:15:31.070-08:00More on the Java IDE comparison<span style="font-weight:bold;">Important</span>: you can read the entire article, as it builds up, at this <a href="http://www.thekirschners.com/articles/Java-IDE-Comprisson.html">URL</a><br /><br /><span style="font-weight:bold;">Code template expansion</span><br /><br />Template expansion is another time saving feature mainstrem java IDEs support nowadays. The feature consists in a setting up an abbreviation which when typed and followed by a specific key combination expands to a full featured piece of code. For example, you could set up psf+TRIGGER to expand to public static final. Or sout+TRIGGER to expand to System.out.println. Once you get used to this feature you become addicted. Templates are written in a simpe language, which can do more or less advanced things, depending on the implementation.<br /><br />IDEA's code template expansion feature is the most advanced, mainly because the template definition language takes advantege of the state of the art code querying mechanism that is built into this IDE. When defining templates in IDEA you can query variables of a certain type, or of certain types.<br /><br />For example, the following template could expand into while (iterator.hasNext()) { Person person = (Person)iterator.next() } and the cursor will be placed where the END tag is.<br /><br />while($ITER$.hasNext()){ $TYPE$ $VAR$ = $CAST$ $ITER$.next(); $END$ }<br /><br />This is cool already, but it gets even better when you notice that you can ask IDEA to replace $ITER$ with variables of a certain type - in this case, Iterator. This can be done by specifying that $ITER$ is a variableOfType("java.util.Iterator"). After doing so, when the code is expanded, IDEA will ask you to choose one of iterators in scope. You can also specify that $TYPE$ should take the value rightSideType(). This takes effect with typed collections in jdk 1.5 - at expansion time TYPE will automatically be replaced with the type of the elements contained in the collection. Regarding $VAR, you can ask IDEA to suggest a variable name, by setting it to suggestVariableName(). If you do so IDEA will propose you variable names based on the contained type. For example, if the type is ImageDescriptor IDEA will propose descriptor and imageDescriptor. All you have to do is choose the name you like most or type your own if your not happy with any of the default ones. Choosing one of the proposed choices, however, tends to result in very readable code.<br /><br />It's possible and very easy to write your own templates. I wrote one to help me initialize log4j loggers. This is the typical situation where template code expansion is very handy. Initializing a logger is an annoing, repetetive task which doesn't have anything to do with the business logic you write. Here is a small template that helps you deal with the problem:<br /><br />private static final Logger log = Logger.getLogger($CLASS_NAME$.class);<br /><br />Then you insruct IDEA to give $CLASS_NAME$ the value className(), register your template under the logdecl abbreviation and you're set. All you have to do from now on is type logdecl+TAB and that IDEA will declare that annoying logger for you.<br /><br />Aparently Eclipse offers code template expansion too, but I haven't been able to make it work. Just couldn't find it. But apparently it's there. But if I can't find it it's just like it wouldn't be.... hmmm......<br /><br />Netbeans offers code template expansion with almost the same features as IDEA - it's slightly less flexible though. You can define your templates, define shortcuts - I have the feeling there are less options then in IDEA. On the other hand, I've not been able to change the activation key - which is SPACE, by default. Also, the activation sequence is kinda weird: the template is only expanded if you press SPACE just after the abbreviation. If you type the abbreviation move your cursor, then comme back and try to expand, it doesn't work. Have to delete the last letter, retype it and quickly press SPACE . I haven't been able to change the activation key - the config dialog let's you change it, SPACE doesn't work any more, but the new key doesn't work either.<br /><br />The winner here is IDEA again, with Netbeans comming in second and Eclipse third.<br /><br /><span style="font-weight:bold;">Getter / Setter / Constructor generation</span><br /><br />Getter / setter / constructor generation features are comparable in IDEA and Eclipse. Both products offer quite complete features and there is nothing much to say on this matter. Netbeans has a slightly different approach on getter / setter generation: the feature is not available under the "source" menu, but under "refactoring", and it's called "encapsulate fields". A little wierd - I wouldn't think about this as refactoring - but hey, the feature is there. If I had some trouble finding the getter setter generation feature, I was totally unable to find an action to let me generate constructors. This is not a very good point for Netbeans, as constructor generation is a very widely used feature. The feature may be there but if I need more the 5 minutes to find it, it's just like it's missing. So the winners in this category are IDEA and Eclipse with similar and equally easy to use features with Netbeans comming in third, offering hard to find, not so easy to use functionality.Emil Kirschnerhttp://www.blogger.com/profile/12037382448539987423noreply@blogger.comtag:blogger.com,1999:blog-7702269.post-1137684757635894082006-01-19T07:31:00.000-08:002006-01-19T07:32:37.653-08:00IDEA live templates for log4j<p>Live templates are a neat feature in modern IDEA - btw, I'll discuss it in the next episode of my IDE comparison article series. Meanwhile for all IDEA and Log4J users out there, this is a set of live templates I wrote to help me deal with Log4J logger declarations and inserting logging lines in my code:<br /><br /><pre><br /><?xml version="1.0" encoding="UTF-8"?><br /><templateSet group="logging"><br /> <template name="ldeb" value="if ($LOGGER$.isDebugEnabled()) $LOGGER$.debug("$END$");" description="Loggs in debug mode" toReformat="false" toShortenFQNames="true"><br /> <variable name="LOGGER" expression="variableOfType("org.apache.log4j.Logger")" defaultValue="log" alwaysStopAt="true" /><br /> <context><br /> <option name="JAVA_CODE" value="true" /><br /> <option name="JAVA_COMMENT" value="false" /><br /> <option name="JAVA_STRING" value="false" /><br /> <option name="XML" value="false" /><br /> <option name="HTML" value="false" /><br /> <option name="JSP" value="false" /><br /> <option name="COMPLETION" value="false" /><br /> <option name="OTHER" value="false" /><br /> </context><br /> </template><br /> <template name="lerr" value="$LOGGER$.error("$END$");" description="Loggs in error mode" toReformat="false" toShortenFQNames="true"><br /> <variable name="LOGGER" expression="variableOfType("org.apache.log4j.Logger")" defaultValue="log" alwaysStopAt="true" /><br /> <context><br /> <option name="JAVA_CODE" value="true" /><br /> <option name="JAVA_COMMENT" value="false" /><br /> <option name="JAVA_STRING" value="false" /><br /> <option name="XML" value="false" /><br /> <option name="HTML" value="false" /><br /> <option name="JSP" value="false" /><br /> <option name="COMPLETION" value="false" /><br /> <option name="OTHER" value="false" /><br /> </context><br /> </template><br /> <template name="linf" value="if ($LOGGER$.isInfoEnabled()) $LOGGER$.info("$END$");" description="Loggs in info mode" toReformat="false" toShortenFQNames="true"><br /> <variable name="LOGGER" expression="variableOfType("org.apache.log4j.Logger")" defaultValue="log" alwaysStopAt="true" /><br /> <context><br /> <option name="JAVA_CODE" value="true" /><br /> <option name="JAVA_COMMENT" value="false" /><br /> <option name="JAVA_STRING" value="false" /><br /> <option name="XML" value="false" /><br /> <option name="HTML" value="false" /><br /> <option name="JSP" value="false" /><br /> <option name="COMPLETION" value="false" /><br /> <option name="OTHER" value="false" /><br /> </context><br /> </template><br /> <template name="logdec" value="private static final Logger $LOGGER$ = Logger.getLogger($CLASS_NAME$.class);$END$" description="Declares a log4J private static final logger" toReformat="true" toShortenFQNames="true"><br /> <variable name="LOGGER" expression="" defaultValue=""log"" alwaysStopAt="true" /><br /> <variable name="CLASS_NAME" expression="className()" defaultValue="" alwaysStopAt="false" /><br /> <context><br /> <option name="JAVA_CODE" value="true" /><br /> <option name="JAVA_COMMENT" value="false" /><br /> <option name="JAVA_STRING" value="false" /><br /> <option name="XML" value="false" /><br /> <option name="HTML" value="false" /><br /> <option name="JSP" value="false" /><br /> <option name="COMPLETION" value="false" /><br /> <option name="OTHER" value="false" /><br /> </context><br /> </template><br /> <template name="lwarn" value="$LOGGER$.warn("$END$");" description="Loggs in error mode" toReformat="false" toShortenFQNames="true"><br /> <variable name="LOGGER" expression="variableOfType("org.apache.log4j.Logger")" defaultValue="log" alwaysStopAt="true" /><br /> <context><br /> <option name="JAVA_CODE" value="true" /><br /> <option name="JAVA_COMMENT" value="false" /><br /> <option name="JAVA_STRING" value="false" /><br /> <option name="XML" value="false" /><br /> <option name="HTML" value="false" /><br /> <option name="JSP" value="false" /><br /> <option name="COMPLETION" value="false" /><br /> <option name="OTHER" value="false" /><br /> </context> <br /> </template><br /></templateSet><br /></pre><br /><br /><p>Just copy this content into a XML file (such as logging.xml), place it in ~/.IntelliJIdea50/config/templates/ and enjoy.Emil Kirschnerhttp://www.blogger.com/profile/12037382448539987423noreply@blogger.comtag:blogger.com,1999:blog-7702269.post-1134599041589049472005-12-14T14:21:00.000-08:002005-12-21T14:39:50.080-08:00IDEA vs. Eclipse vs. NetBeans - which one to choose?<span style="font-weight:bold;">Introduction</span><br /><br />Eclipse and IDEA are definitely the best java IDEs around, and nobody can deny that. Now about the two of them, a flame war is going on, similar to Unix vs. Windows, VI vs. Emacs, Java vs. .Net.... NetBeans on the other hand, wasn't a very bright product in the past, but version 5 (beta) has a decent set of features that makes it almost a serious competitor for Eclipse and IDEA. Which one is the best? Which one is the best for you? What's the value and the subtle differences between all those cryptic features that seem all the same on paper? Hope this articles will help clarify some of these questions and more importantly, help you choose.<br /><br /><span style="font-weight:bold;">Code writing assistance</span><br /><br />Code writing assistance is one of the most important features in today's modern java IDEs. It's what helps you gain time, lets you concentrate on the logic instead of searching for the name of that method you need to call, helps you analyze the code, reorganize it, make it more readable and maintainable.<br /><br /><span style="font-weight:bold;">Code completion</span><br /><br />Code completion has been around for many years, in many development environments, not just JAVA ones. So the obvious question is: what could possibly get better about this? Well, you'll be surprised...<br /><br />All three IDEs I'm examining here offer some form of code completion. If you type a few letters and then you press CTRL+SPACE, the IDE will offer you a set of choices: class names or variable names. The most advanced code completion features are offered by IDEA. The big difference when compared to the others is that IDEA's code completion is context aware. This means that options that are offered to you when you initiate code completion are filtered with respect to the code fragment where the cursor is located. Indeed, instead of proposing you all the classes of the universe - the universe being your project class path :-) - IDEA will only offer you a reduced, less confusing, set of choices which in 95% of the situations will result in compiling code and in 85% of the cases they'll promote on top of the suggestions list the entity that you're actually looking for. They call it smart code completion and it's not an exaggeration.<br /><br />How does smart code completion work? For example, if you have int variables a, b, c, d and double x, y, z and you type a = CTRL+SHIFT+SPACE, IDEA will only propose you only b, c and d. Definitely not x, y or z and definitely not class names or other entities. For return statements: if your method returns Person, if you type return CTRL+SHIFT+SPACE IDEA will only propose you variables of type Person or its specializations and methods that return instances of Person. Same thing goes for throws statements: when activating code completion after a throw statement IDEA will only propose you instances of the exceptions that are declared to be thrown by the method which you edit.<br /><br />Smart code completion also works very well when instantiating objects: in assignments, return statements or throw statements, when you activate code completion after the new keyword IDEA will propose you only suitable constructors, as previously explained. The detail level is pushed to limits never seen anywhere else. For example, suppose you have a variable called count and you want to initialize it by calling a method on a class. If that class has a getter that contains "count" in its name - such as getCount() or getObjectCount() - that returns the type of the variable, IDEA's smart code completion will preselect that method for you. All you have to do is press ENTER t select it.<br /><br />One of the most important features regarding smart code completion in IDEA is that it can be activated without typing the first letters of he text you want to complete. This is very time saving features as in most cases it prevents you from having to scroll to the beginning or the end of the class to remember how that variable or method is named. IDEA will efficiently look up all variables and methods that match the type of the assignment or of the parameter you're looking for and propose only those. Same thing when you want to cast a reference to an object. Type ( CRTL+SHIFT+SPACE in front of the object you want to cast and IDEA will automatically insert the REQUIRED class name.<br /><br />IDEA expands the concept of code completion by transforming it into an efficient code querying mechanism, which is ready to serve the right variable, parameter, method or class names whenever you need it, with respect to the context in which you invoke the functionality. And it also does a very satisfactory job in guessing which variable, parameter or method you wish use and preselecting it for you. Plus, it's extremely easy to use. You don't have to learn many keyboard shortcuts. Whenever you need assistance when writing code, press CTRL+SHIFT+SPACE and you'll be surprised how well it works.<br /><br />Code completion and parameter guessing in Eclipse are disappointing, which is a shame, because I consider ECLIPSE to otherwise be a fairly good product. Compared to IDEA, what you get in Eclipse is a joke. It's as primitive as it can get. This may seem harsh, but its reality. You type int i = CTRL+SPACE and it will propose you huge list of entities containing all the classes in the class path, all variables, all methods.... After scrolling in that list for a while you will eventually find the entity you need. Smart code completion doesn't exist. It's just raw code completion without any context filtering. This is very frustrating because there are signs that the knowledge to implement smart code completion in Eclipse is there. You can see it with the javadoc code completion feature: if you type @throws CTRL+SPACE it will only propose exceptions that are declared by the method for which you write the comment. If I would be to designate a functionality in Eclipse that needs urgent improvements, this would be it. Code completion is one of the first features a new user comes in contact with. If Eclipse wants to attract IDEA users, the primitive code completion features now in place are a huge barrier. It's the main reason that kept me from adopting it.<br /><br />Netbeans 5 (beta) offers about the same level of code completion functionality as Eclipse does, but slightly better and easier to use. You get class and local variables on top of the list and classes and packages at the end. That's a small detail but an important improvement already.<br /><br />Well, the winner in this category is - you must have guessed - IDEA. By far. Netbeans comes in second, followed by Eclipse. Both offer very basic code completion but the functionality in Netbeans is slightly more usable.Emil Kirschnerhttp://www.blogger.com/profile/12037382448539987423noreply@blogger.comtag:blogger.com,1999:blog-7702269.post-1130061443274991902005-10-23T02:48:00.000-07:002005-10-23T14:31:36.493-07:00TESTARE - junit integrationI've started to work on JUnit integration for TESTARE, my <a href="http://www.thekirschners.com/software/testare/testare.html">java testing framework</a>. My approach for this integration effort is to enable projects that have already invested a great deal into a JUnit based test development effort to easily implement in container testing. Apart from that, there are a few other advantages coming out of this, like TESTARE test cases will be automatically discovered and executed by JUnit test case/suite runners, like those in IDEA and Eclipse - this is already starting to work, the code is in CVS and you can do a checkout at <a href="http://testare.dev.java.net">java.net</a><br /><br />The goal is also to support at least one other mainstream testing framework, like TestNG. This is because I don't want to discriminate TestNG users over JUnit users. I see TESTARE as a new layer, that enables in container testing for regular testing frameworks.<br /><br />I would like to use this opportunity to notice the lack of support JUnit offers for writing extensions. In order to properly integrate TESTARE, I absolutely need the following:<br />* receive an event before the execution of the first test in the suite<br />* receive an event after the execution of the last test in the suite<br />* enable extension writers to register a factory to instantiate tests present in a class<br /><br />Right now I don't have any of these. It would be really great if the JUnit team would rethink their approach on how to handle extensions. This would make the life much more easier for many extension projects. But I promise I'll write more in details about this and approach the JUnit team about it.Emil Kirschnerhttp://www.blogger.com/profile/12037382448539987423noreply@blogger.comtag:blogger.com,1999:blog-7702269.post-1126130337611904332005-09-07T14:43:00.000-07:002005-09-07T15:00:01.436-07:00xstream & jdk1.5 annotations - continuedIt seems my xstream / annotations hack had some success. I've contacted the xstream development team and told them about it, and it was very well received. After a short discussion with the development community we agreed on a more simple to use set of annotations. Joe plans to create a sub-project of xstream to contain extensions different people contributed, and add the annotation hack in there. Meanwhile, Chung-Onn Cheong had some interesting ideas about new annotations and it seems he'll be contributing some code as well.Emil Kirschnerhttp://www.blogger.com/profile/12037382448539987423noreply@blogger.comtag:blogger.com,1999:blog-7702269.post-1123245987932672512005-08-05T05:12:00.000-07:002005-08-05T05:47:38.370-07:00xstream & jdk1.5 annotations<p>I wanted to use XStream for persisting a small ammount of configuration data in one of my pet projects. XStream is a java to XML object serializer. It comes very close to perfection: it's small, fast, free, and the learning courve is of aproximately 20 seconds. To use it, all we have to write is: new XStream().toXml( yourObject , new FileWriter( "your.file.name" ) ) if we want serialize an object to disk and new XStream().fromXml(new FileReader("your.file.name")) if we want to deserialize one<br /><p>The only (slight) problem with it is that if we do just that, we'll probably end up with an ugly and difficult to read xml file, because XStream uses java fully qualified class names and attribute names as XML tags. In order to address this, XStream enables us to create aliases for class and attribute names. These aliases will be then used to form XML tags, resulting in much readable XML content. This feature is also very simple to use: we just invoke XStream.alias(...) and XStream.aliasField(...) before writing / loading your object. So you'd end up writing a few static utility methods that would configure your XStream object with required aliases. Problem, however, is that that's a pain to maintain: each time you update your data model (add / remove a class, add / remove a field), you will have to update the aliases. It would be really nice if the aliases for classes and fields would be stored along with the data model itself. This way we have all information related to a class in one file, we don't have to remember to go and modify anothe one. That much easier to maintain, as all the information regarding a class and its attributes is under your eyes when you open that class.<br /><p>The annotations feature in JDK 1.5 enables us to do just that: be able to decorate classes and fields with whatever information we need. In this case we'll decorate them to specify xstream aliases. To achieve this I have created these four annotations:<br /><br /><pre><br />@Retention(RetentionPolicy.RUNTIME)<br />@Target(ElementType.TYPE)<br />public @interface xstreamAlias {<br /> public String alias();<br />}<br /><br />@Retention(RetentionPolicy.RUNTIME)<br />@Target(ElementType.FIELD)<br />public @interface xstreamAliasField {<br /> public String alias();<br />}<br /><br />@Retention(RetentionPolicy.RUNTIME)<br />@Target(ElementType.FIELD)<br />public @interface xstreamContainedType {<br /> public Class type();<br />}<br /><br />@Retention(RetentionPolicy.RUNTIME)<br />@Target(ElementType.TYPE)<br />public @interface xstreamFileName {<br /> public String name();<br />}<br /></pre><br /><br /><p>These annotations serve each a different goal:<br /><ul><br /><li>xstreamAlias can decorate classes and can be used to specify class aliases.<br /><li>xstreamAlias can decorate fields and can be used to specify field aliases.<br /><li>xstreamContainedType can decorate fields and can be used to specify what classes are stored in collection fields.<br /><li>xstreamFileName can decorate classes and can be optionally used to indicate the name of the file in which instances of that class must be saved.<br /></ul><br /><br /><p>This is what a couple of decorated classes look like:<br /><pre><br />@xstreamFileName (name = "parties")<br />@xstreamAlias(alias = "parties-container")<br />public class PartyContainer {<br /> @xstreamAliasField(alias = "parties")<br /> @xstreamContainedType(type = PartyPersistent.class)<br /> public List<partypersistent> parties;<br /><br /> public PartyContainer() {<br /> parties = new ArrayList<partypersistent>();<br /> }<br />}<br /><br />@xstreamAlias(alias = "party")<br />public class PartyPersistent implements Serializable {<br /> @xstreamAliasField(alias = "pk")<br /> private String pk;<br /> <br /> @xstreamAliasField(alias = "name")<br /> private String name;<br /> <br /> @xstreamAliasField(alias = "last-name")<br /> private String lastName;<br /> <br /> @xstreamAliasField(alias = "is-owner")<br /> private boolean isOwner;<br /> <br /> @xstreamAliasField(alias = "is-organization")<br /> private boolean isOrganization;<br />}<br /></pre><br /><br />And finally, this is the class that contains the static methods used to configure the XStream object:<br /><pre><br />public class XStreamPersister {<br /> private static final Set configuredTypes = new HashSet();<br /><br /> public static synchronized String configureAliases(Class topLevelClass, XStream xstream) {<br /> Class crtClass = topLevelClass;<br /> String fileName;<br /> xstreamFileName xstreamFileName = (xstreamFileName) crtClass.getAnnotation(xstreamFileName.class);<br /> if (xstreamFileName != null)<br /> fileName = xstreamFileName.name();<br /> else<br /> fileName = topLevelClass.getName();<br /><br /> configuredTypes.clear();<br /> configureClass(crtClass, xstream);<br /><br /> return fileName;<br /> }<br /><br /> private static synchronized void configureClass(Class crtClass, XStream xstream) {<br /> if (configuredTypes.contains(crtClass))<br /> return;<br /><br /> xstreamAlias xstreamAlias = (xstreamAlias)crtClass.getAnnotation(xstreamAlias.class);<br /> if (xstreamAlias != null)<br /> xstream.alias(xstreamAlias.alias(), crtClass);<br /><br /> configuredTypes.add(crtClass);<br /><br /> Field[] fields = crtClass.getDeclaredFields();<br /> for (Field field : fields) {<br /> xstreamAliasField xstreamAliasField = (xstreamAliasField) field.getAnnotation(xstreamAliasField.class);<br /> if (xstreamAliasField != null)<br /> xstream.aliasField(xstreamAliasField.alias(), crtClass, field.getName());<br /> Class fieldType = field.getType();<br /> if (Collection.class.isAssignableFrom(fieldType)) {<br /> xstreamContainedType xstreamContainedType = (xstreamContainedType)field.getAnnotation(xstreamContainedType.class);<br /> if (xstreamContainedType != null) {<br /> Class containedClass = xstreamContainedType.type();<br /> configureClass(containedClass, xstream);<br /> }<br /> } else if (!field.getType().isPrimitive()) {<br /> configureClass(field.getType(), xstream);<br /> }<br /> }<br /> }<br /></pre><br /><br /><p>Once you have configured you xstream object, this is an example of what you get if you serialize an instance of the PartyContainer class from up the page:<br /><pre><br /><parties-container><br /> <parties><br /> <party><br /> <pk>c1ab52418523b250:-3c9bdb8b:1057839414b:-7ffe</pk><br /> <name>aaaaaaaa</name><br /> <last-name>aaaaaaaaa</last-name><br /> <is-owner>false</is-owner><br /> <is-organization>false</is-organization><br /> </party><br /> <party><br /> <pk>c1ab52418523b250:-3c9bdb8b:1057839414b:-7ffd</pk><br /> <name>bbbbb</name><br /> <last-name>bbbbbbb</last-name><br /> <is-owner>false</is-owner><br /> <is-organization>false</is-organization><br /> </party><br /> </parties><br /></parties-container><br /></pre><br /><p>I think we all agree that's more readable then this:<br /><pre><br /><com.thekirschners.docmanager.localimpl.datamodel.v1.PartyContainer><br /> <parties><br /> <com.thekirschners.docmanager.localimpl.datamodel.v1.PartyPersistent><br /> <pk>c1ab52418523b250:55c36e5f:105783da309:-7fff</pk><br /> <name>aaaaaaaa</name><br /> <lastName>aaaaaa</lastName><br /> <isOwner>false</isOwner><br /> <isOrganization>false</isOrganization><br /> </com.thekirschners.docmanager.localimpl.datamodel.v1.PartyPersistent><br /> <com.thekirschners.docmanager.localimpl.datamodel.v1.PartyPersistent><br /> <pk>c1ab52418523b250:55c36e5f:105783da309:-7ffe</pk><br /> <name>bbbbb</name><br /> <lastName>bbbbb</lastName><br /> <isOwner>false</isOwner><br /> <isOrganization>false</isOrganization><br /> </com.thekirschners.docmanager.localimpl.datamodel.v1.PartyPersistent><br /> </parties><br /></com.thekirschners.docmanager.localimpl.datamodel.v1.PartyContainer><br /></pre><br /><p>Hope this post will help people make better use of xstream and also get an idea of what annotations could be used for. Since this is my second hack arround annotations (see autoui) I think everybody notices a really like this feature. I think it's one of the most usefull one in jdk 1.5 as opposed to generics which, in my opinion, are the worst implementation of a new concept we've ever seen in the history of Java. <br /><br /><p>If you know what templates can do in C++ and you expect generics to provide comparable features, just forget about it. My generics rant will be online soon :-)Emil Kirschnerhttp://www.blogger.com/profile/12037382448539987423noreply@blogger.comtag:blogger.com,1999:blog-7702269.post-1120827979530870482005-07-08T05:55:00.000-07:002005-07-08T06:06:19.536-07:00TESTAREI have developed a test framework for distributed java applications wich is available on java.net (<a href="http://testare.dev.java.net/"/>http://testare.dev.java.net/</a>). It has quite the same feature set as JUnit when used for client side testing, but it brings real value when used to test distributed java applications by simplifying and speading up the test development process. A white paper is available <a href="https://testare.dev.java.net/files/documents/3180/15999/file_15999.dat?filename=testare%20%2d%20an%20troduction%2epdf"/>here</a> and the binary distribution can be downloaded from <a href="https://testare.dev.java.net/files/documents/3180/15213/testare-bin-0.1.zip"/>here</a>.Emil Kirschnerhttp://www.blogger.com/profile/12037382448539987423noreply@blogger.comtag:blogger.com,1999:blog-7702269.post-1098904835174547622004-10-27T13:17:00.000-07:002007-01-04T15:11:50.190-08:00jdk 1.5 annotations (2)<a href="http://www.thekirschners.com/software/autoui/autoui.html">AutoUI</a> is a jdk 1.5 annotations based mechanism used to automatically build data object editor user interfaces.<br /><br />Why? I develop a pet project which is a lot about editing an object model. With JDK 1.4 I was forced to have an editor panel class for each data class I needed to edit. Each panel can be reused between "Create..." and "Edit..." dialogs, but still I had to spend significant time to:<br />a) initially develop my data editor panels<br />b) keep editor panels in sync with the data model as the later evolves<br /><br />Since I don't have much time for my pet project - I have to work for a living like almost everyone else - I was very keen to find a solution to help me speed up my developments and simplify maintenance. This is when I had the idea: I could use annotations to decorate my data classes with hints on how to build a user interface and have an automated tool that would use reflection to find these decoration at runtime and construct the editor panel accordingly. And since we're at it, the UI could also use reflection to apply editor values to my data objects and the other way around.<br /><br />The logic behind it is quite simple: to construct a panel I was always repeating the same code sequence:<br />for each attribute, I<br /> a) instantiate an editor element (JTextField, JCheckBox, etc)<br /> b) set GridBagConstraints for editor element<br /> c) instantiate a JLabel<br /> d) set GridBagConstraints for the label<br /> e) eventually add a separator<br /><br />All this can very easily be automated, so I quickly coded a prototype and it worked. The advantage is<br />obvious: no more out of sync between data classes and editor classes:<br />- if you add an attribute to your data class, you also immediately decorate it with hints for grid bag layout<br />- if you remove an attribute, you also have remove its decorations<br />- if you rename an attribute or even a super class, you don't even need to touch your UI<br /><br />Having everything in one file simplifies things quite a lot.<br /><br />The associated code was a fragment of my development tree, but I decided to detach it release it as open source, under the Apache V2 license.<br /><br />Current functionality is limited to automated UI construction for classes containing canonic attributes, but I plan to add automated data integrity checks and support for complex attributes, and many others.<br /><br />There is a quick and dirty demo in the com.thekirschners.uitoys.autoui.samples.demo package.<br /><br />Of course, this is just an initial post. I'll continue to release more code and documentation as the project moves along. One important thing to point out is that this project is mainly driven by my pet project's needs (and will continue to be so). However, if I receive feature requests which are of general interest, I'll do my best to include it in the code base. Like in any open source initiative, any contribution to the project, in any form - feature requests, bug reports, feedback, code contributions and/or fixes - is highly welcomed. Please don't hesitate to post your impressions on this blog.<br /><br />download the source package at:<br />http://www.thekirschners.com/autoui.tar.gzEmil Kirschnerhttp://www.blogger.com/profile/12037382448539987423noreply@blogger.comtag:blogger.com,1999:blog-7702269.post-1097871643140305912004-10-15T13:15:00.000-07:002005-07-11T05:01:16.613-07:00jdk 1.5 annotationsi'm playing with jdk 1.5 annotations and thinks look quite fine. I made up of set of user interface annotations which I use to decorate my data objects. Then I have an automatic editor interface builder which construct a GridBagLayout based editor based on the annotations I used to decorate the data class. The automatic UI builder has setter and getter methods that use reflection to initialise the UI from the data object and set object values as edited in the UI, respectively.<br /><br />I'll release everything as open source and post it as soon as I get the time to arrange the code a little bit.Emil Kirschnerhttp://www.blogger.com/profile/12037382448539987423noreply@blogger.com