|
|
|||||||||||||||||||||
Evan Summers's BlogJanuary 2007 ArchivesHTML BuilderPosted by evanx on January 25, 2007 at 05:31 AM | Permalink | Comments (2)
Having defined style objects in the Hyper Style prequel, we build an "HTML builder" to generate HTML/CSS, eg. for this series of articles using quitehyper.dev.java.net.
public class QHyperArticleHtmlBuilder extends QHtmlBuilder { QStyle anchorStyle = createStyle("anchorStyle", a); QStyle sectionStyle = createStyle("sectionStyle", div); QStyle subsectionStyle = createStyle("subsectionStyle", div); ... public String buildSubSectionHeading(String anchorName, String text) { return buildAnchorHeading(subsectionStyle, anchorName, text); } protected String buildAnchorHeading(QStyle divStyle, String anchorName, String text) { QMutableElement element = create(p); element.add(br); element.add(create(a, anchorStyle, name.create(anchorName))) .add(create(div, divStyle, text)); return element.buildHtml(); } public String buildLink(String url, String label) { QMutableElement element = create(a, anchorStyle, href.create(url)); element.add(create(span, underlineStyle)) .add(create(span, linkStyle, label)); return element.buildHtml(); } } where QHtmlBuilder defines the "immutable HTML elements" eg. pre, div, p, et al, from which we create mutable elements, with attributes (eg. name, href, et al), a given style ie. CSS class, child elements, and/or text content. Besides HTML fragments for sections headings and what-not, we get out the CSS text as follows.
<style> pre.javaStyle { font-family: courier new, courier, mono; background-color: #fbfbfb; font-size: 11pt; width: 800px; border: dashed 1px; border-color: lightgray; padding-left: 4px; } ... </style>
Discovering Google ReaderPosted by evanx on January 25, 2007 at 04:52 AM | Permalink | Comments (7)Do you use Google Reader? But why not?! ;) Opensource BusinessPosted by evanx on January 19, 2007 at 05:46 AM | Permalink | Comments (10)Ben Galbraith made the following great point in his recent blog entry in praise of intelligent tools such as IDEA. Maybe it's because I hope to sell software someday, maybe because I know how hard it is to write good software, but for whatever reason, I actually like supporting great ISVs by buying their product. I spend thousands of dollars on ISV products each year because I feel its the right thing to do. IDEA vs competition from opensource options, is an interesting case study of the software market in general. One wants to support vendors producing great stuff, like JetBrains, Atlassian, and the like. But one also wants to support opensource/community projects, which likely present an important part of the future.
If it wasn't for Eclipse and Netbeans, maybe Sun or IBM would have bought JetBrains and opensourced IDEA? Maybe in future JetBrains will opensource IDEA themselves, to drive volume for more niche products? This prospect of a world where all prominent software is free and opensource, is disconcerting because traditionally a small startup business developed some software in order to sell it. But these days the trend is to build free-use websites and opensource software to drive other revenues eg. professional services. So maybe the future is that most startups will build on opensource software to add particular value eg. MyEclipse, or create opensource software to drive volume eg. Terracotta, and generally provide complementary products and services around opensource software.
But hopefully there'll always be opportunity for small businesses
to create great new software from scratch, and sell it, pure and simple?
Later, you might find opensource equivalents snapping at your heels.
But if you're competing against "free" then at least your product
really has to be good, and you gotta keep making it even better, or die trying.
Gooey Bean AspectPosted by evanx on January 15, 2007 at 06:36 AM | Permalink | Comments (4)
We use CGLIB to enhance a half-baked Java Bean with no firePropertyChange() invocations in its setters, into a bean that does fire PropertyChangeEvent's from its setters.
Our QBeanInterceptor registers the PropertyDescriptor's setters methods into a setterMap.
public class QBeanInterceptor extends QInterceptor { BeanInfo beanInfo; Map<Method, PropertyDescriptor> setterMap = new HashMap(); BeanPropertySupport beanAnnotation; boolean fireByDefault; ... public Object invoke(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable { Object oldValue = null; Object newValue = null; PropertyDescriptor propertyDescriptor = null; if (args.length == 1 && fireAtWill(method)) { newValue = args[0]; propertyDescriptor = setterMap.get(method); if (propertyDescriptor != null) { oldValue = getOldValue(target, propertyDescriptor); } } Object result = super.invoke(target, method, args, proxy); if (propertyDescriptor != null) { QBean bean = (QBean) target; bean.getPropertyChangeSupport().firePropertyChange( propertyDescriptor.getName(), oldValue, newValue); } return result; } ... } where if the method is a key to an associated PropertyDescriptor in setterMap, then we invoke firePropertyChange() to fire a PropertyChangeEvent.
Here is a trivial demo that is hardly worth downloading. And it's quite large, because it depends on a CGLIB jar.
Jelly Beans 1: Mock PersistencePosted by evanx on January 12, 2007 at 04:02 AM | Permalink | Comments (0)This Jelly Beans series deals with data entities, as required for the Gooey Beans series' demos. Together with Hyper Beans, i'm calling them the Foundation Trilogy :) And yes, it's a scifi/fantasy trilogy in 42 parts, essentially about writing database applications using Swing. So we create our "database" as an in-memory-only object graph, which is populated with test data when we startup our app. That is, we "save" our entity beans in a TreeMap, without actually persisting them to a database. For GUI prototyping and demos, this is not as useless as it sounds ;)
We create (and delete et al) test data for the Person Info demo used in the sibling Gooey Beans series.
We create test data at startup as follows.
public class ContactTestData { ... DPerson jackSparrow = createPerson("jsparrow", "Jack Sparrow", "captjs@blackpearl"); ... DCountry jamaicaCountry = createCountry("jm", "Jamaica", "jm", 1876, jmd); ... DRegion portRoyalRegion = createCityRegion(jamaicaRegion, "Port Royal"); ... protected DPerson createPerson(String personId, String personName, String emailAddress) { DPerson person = new DPerson(); person.setPersonId(personId); ... entityManager.personInfo.save(person); return person; } ... } where entityManager declares our "entity info" objects eg. DPersonInfo, which serve as "data access objects" eg. for DPerson entities.
Property Problems, Solutions and WishesPosted by evanx on January 11, 2007 at 01:50 AM | Permalink | Comments (7)Here are some problems and possible solutions (today) relating to bean properties.
Problem. We don't wanna write lots of getters and setters, or see them. Solution. We use our IDE to generate them. Wishlist. Maybe we wanna fold basic getters and setters right out of view en masse. Another Wishlist. People wanna see the introduction of property keywords eg. property, readonly, etcetera. Personally, i'm happy with getters and setters with the help of my IDE.
Problem. Property names are strings, which are not geared for IDEs (besides being highlightable as strings as opposed to numbers and keywords). So we can't expect, and don't get any help from our IDE, or even compiler. All we can expect is runtime errors, D'oh! Solution. We unit test our code so that we catch problems before they can hurt us at runtime. Further Solution. We might implement BeanInfo meta-classes where we explicitly expose the bean property descriptors. For example, in Gooey Beans Info, we introduce a PropertyDescriptor wrapper with methods that our forms and table models will invoke eg. property.get(bean) and property.set(bean, value), which support validation, type conversion, and throw useful exceptions. Wishlist. I wish for a language notation eg. Person@surname to access a PropertyDescriptor in a convenient, auto-completable, verifiable and refactorable way in my favourite IDE.
Problem. Lazy people like me don't wanna implement all the JavaBean boilerplate to fire PropertyChangeEvent's. Solution. We can use AOP to introduce PropertyChangeSupport and fire PropertyChangeEvent's, eg. using CGLIB. We use our explicit BeanInfo meta-class as a factory to create our enhanced beans. (I'll try this out in a follow up blog.) Wish. I wish my favourite IDE could create new Java Beans (with PropertyChangeSupport) and generate setters which fire PropertyChangeEvent's, and code-fold them to look like POJO's with regular setters. Further Wish. I wish for a standard tool in my favourite IDE's default build process, for annotation processing for compile-time AOP code generation, to enhance classes ala Spoon at compile-time. This could support a @JavaBean aspect annotation to request that a POJO be enhanced into a Java Bean ie. having observable properties.
Gotcha Property DescriptorPosted by evanx on January 09, 2007 at 02:54 AM | Permalink | Comments (8)
As Richard Bair points out we really need a way to get a PropertyDescriptor easily, ie. meta data and support for bean properties. For example, we wanna reference bean properties for beans binding in a safe and auto-completable way, as discussed in Gooey Beans Info. Since hash (#) already denotes fields and methods in the javadoc notation, I reckon hash might be used to get fields and methods, rather than property descriptors. I guess candidates for denoting a PropertyDescriptor include a colon eg. Person:surname, and at eg. Person@surname. I was so happy to leave behind arrows (->) when i moved from C to Java, and the thought of now seeing them in Java, is um, too terrible to contemplate ;) One could argue that if one's favourite IDE supported this notation, eg. where Person@surname is a code-fold of sorts for a static utility invocation eg. BeanInfoSupport.getPropertyDescriptor(Person.class, "surname"), and the IDE supported auto-completion, verification and refactoring of these references, then that would do. However, a big part of why we need property references, is because these are useful in other APIs, eg. beans binding and what-not. So they need to be supported in the language if they are to positively influence the design of other APIs. For instance, APIs might consider referencing properties by PropertyDescriptor in addition to property names, in the event of convenient PropertyDescriptor references coming into the language eg. Person@surname. Also, new PropertyDescriptor wrappers might be introduced eg. BoundPropertyDescriptor, which wraps a PropertyDescriptor together with a specified bean instance, eg. theChoosenOne@surname as opposed to Person@surname. Incidently, on the issue of observable properties, i believe that AOP might be the answer eg. to fire PropertyChangeEvent's eg. using dynamic proxies, CGLIB, or compile-time code generation from annotation processing. If property setters and getters are to be generated by the compiler where these don't exist, hopefully this would be performed by a tool which supports code generation from aspects indicated by annotations eg. a @JavaBeanAspect declared on the class.
Five ThingsPosted by evanx on January 06, 2007 at 04:44 AM | Permalink | Comments (1)Before someone tags me (and then i have to find five others who haven't been tagged yet, which will require some effort on my part), and in case someone doesn't ;) here goes me taking the fifth...
It's on CVS here
cos i like to use an editor to edit stuff eg. Netbeans,
and right-click to commit, images and all.
| |||||||||||||||||||||
|
|