Wednesday July 30, 2008 |
Isopaleocopria
Gregory Murphy's Blogorrhea |
|
|
Ruby Eye for the Java guy: Constants In Java, it is common to use public, final, static fields to represent utility constants. Since the fields are public, they can be used from any package; and since they are final, values cannot be assigned to them once they have been initialized. If the field is a primitive type, such as It would seem like the need for an API to expose constants is universal, and so should find expression in every language. How to do this in Ruby? In Ruby, any field that begins with an upper-case letter is treated as constant. If you attempt to assign to a constant more than once, the interpreter will issue a warning. Constants may be defined inside of a class, and since the Ruby Class class inherits from Module, you can use the module "::" accessor syntax to read the constant's value:
class MyClass
MY_VAR = "xxx"
end
puts MyClass::MY_VAR #=> "xxx"
MyClass::MY_VAR = "yyy" #=> "warning: already initialized constant MY_VAR"
However, the Ruby String class is mutable, so the constant is still open to modification:
MyClass::MY_VAR[1] = "z" puts MyClass::MY_VAR #=> "xzx"Everything in Ruby is an object, and all objects inherit from the Object class. Object defines a freeze method, which, once invoked, prevents any further modification to the object's state. Once frozen, an object can never be "thawed". So a final, immutable class constant in Ruby might look like this:
class MyClass
MY_VAR = "xxx"
MY_VAR.freeze
end
puts MyClass::MY_VAR #=> "xxx"
MyClass::MY_VAR = "yyy" #=> "warning: already initialized constant MY_VAR"
MyClass::MY_VAR[1] = "z" #=> "in '[]=': can't modify frozen string (TypeError)
The attempt to modify the frozen object results in an unchecked error, and execution halts. Re-assigning to the constant results in a warning only, and execution continues. It is possible to make assignment a fatal error, too, if we wrap the constants in a module, and freeze the module:
module MyModule
MY_VAR = "xxx"
MY_VAR.freeze
end
MyConstants.freeze
MyModule::MY_VAR = "YYY" #=> "can't modify frozen module (TypeError)
Be careful, if you want to "mix in" the module's functionality, callers of your class will access the module's constants through an unfrozen path:
class MyClass
include MyConstants
end
MyClass::VAR = "qqq"
MyClass::VAR[1] = 'r'
puts MyClass::VAR #=> "qrq"
One solution might be to freeze your class, if you want to guarantee the immutability of everything in the class. If you want to leave the class open to extension or modification, you could wrap the included constants in an inner module:
module MyConstants
VAR = "xxx"
VAR.freeze
end
MyConstants.freeze
class MyClass
class Constants
include MyConstants
end
Constants.freeze
end
puts MyClass::Constants::VAR #=> "xxx"
(2008-07-30 10:13:21.0)
Permalink
A few months ago, I started to play with the free version of Google Sketchup. After mastering the basics, I was able to produce a few, prototypical architectural features, such as cornices and fluted columns. Last week I put the tool to a more practical use. My wife wanted a small wine rack in our kitchen. Counter space is scarce, so we decided to try something under the cupboards. I used Sketchup to design the rack. Being able to visualize it from any angle was helpful, and we eliminated some early designs when we realized they would look funny from certain angles, or prove impractical in the small space. Here is the final "sketchup":
I downloaded the wine bottle from the Google Sketchup 3D Warehouse, and dropped it in the model. And here is the actual rack:
I probably spent about six hours on the design, including the two that I discarded. With practice I'll become faster, I'm sure. The rack itself took only a few hours - including ten minutes to sand the initial coat of primer that my three-year old applied. (2007-05-14 07:09:50.0) PermalinkRuby script to toggle CVS root in a workspace Sandip Chitale posted a Java program that toggles the CVS root setting of a workspace that is already checked out (see A simple program to toggle CVSROOT of existing checked out workspace). At the end of his post, Sandip solicits alternative solutions. I have been playing around with Ruby, and was curious as to how much more compactly the same logic could be expressed in Ruby. Stripped of empty lines and comments, Sandip's Java solution weighs in at 83 lines. That's roughly four times the 16 lines required for a roughly equivalent program in Ruby, which I give below. The Java program has explicit exception handlers, which I chose to leave out, since both programs will leave the repository in a corrupted state if IO fails midway. # A simple program to fix the CVSROOT. # # One may check out a cvs workspace using a CVSROOT e.g. #(2007-04-26 16:49:13.0) Permalink Comments [2] "Neutered Theme" for Java Studio Creator The basic components that ship with Java Studio Creator (and with its successor, Visual Web Pack> for NetBeans) derive their look and feel from a theme. If you need to apply your corporate colors to an entire application, themes make the job easier. But if you want to adjust the appearance of just one component, or make a set of components play nicely with other styles, themes can get in the way. Unfortunately, you can't just unplug the theme from an application. In addition to things like fonts and colors that affect only the look of an application, the theme defines things that are critical to component behavior, like messages and client-side scripts. To help in these situations, I put together a "neutered theme." This is a theme from which everything extraneous has been excised. With the neutered them, most of the components end up looking pretty much like their standard JSF counterparts. For example, here is a basic button rendered with the default theme: ![]() Notice the border, gradient color, and text font, all of which are derived from the default theme. Switch to the neutered theme, and the button looks pretty much like a plain HTML input button: ![]() What if you want one button on your page to be yellow? If your application relies on the default theme, and you set a button's style property so that it's background is yellow, the component remains colored a gradient blue. That's because your CSS settings in the component property are conflicting with CSS settings in the theme. But if you use the neutered theme, you'll get what you want: ![]() Neutered themes are also useful when developing portlets, as it reduces the likelihood of conflict between portlet theme styles and styles assigned to a whole portal page. How to use the Neutured Theme
Update to PropertyResourceProvider There was a bug in the first version of the PropertyResourceProvider that I made available from this blog a few months ago (see DataProvider component for internationalizing Creator applications), which manifested itself in the glassfish application server. The order of two elements in the library's faces-config file was incorrect. I have fixed the bug and updated the complib available for download. You can download the updated PropertyResourceProvider Component Library here. (2006-12-13 15:07:06.0) Permalink NetBeans Free-Form Projects as Library Wrappers When the developer defines a library in NetBeans 5.x, the library definition is stored locally, in the user directory. This makes it difficult to share library definitions among more than one workspace. While library definitions are stored locally, references to them, in the form of entries in a project's properties file, are typically stored along with all other project files, in a remote code repository. When a user first fetches the project from the repository and opens it in NetBeans, a missing references error will occur. All missing local library definitions must be created anew in each local workspace. One solution to this problem is to store shared libraries in the remote workspace, and to make projects depend directly on the libraries' constituent JAR files. Such dependencies are stored in the project's properties file as relative paths to the JAR files, so assuming that the directory structure that includes both project and library remains the same in all users' workspaces, no local definitions are needed. There are however drawbacks to this solution. Under the Libraries node of the project logical view, only the JAR file name is displayed. If your project depends on a large number of libraries, it can be difficult to distinguish among them by file name alone. The names may by cryptic, or worse, there may be files in different directories that share the same name. There is also no way of determining from the project logical view that a group of JAR files form a logical unit, unless they share a common infix. As an example, consider the following project, in which one library provided JAR files ![]() There is a hack that I have used to improve the quality of the information available about JAR files in the project logical view, which does not require use of the local storage. Instead of grouping them into library definitions, I add them to free-form projects. Projects may then be declared to depend on the library wrapper projects. Here is the same example, with the JAR files from the two libraries exported from two free-form library projects: ![]() How to create a free-form library wrapper project To create a free-form library wrapper project, start by putting all JAR files that belong together into a directory, which will serve as the project root directory. For this example, I will define two libraries, 01 and 02, the first containing two JAR files, lib01/aaa.jarlib01/bbb.jarlib02/aaa.jar
./src. You will also need a stub ant build script. Add the following contents to the file build.xml in the project directory:
<project name="01_Library_Wrapper" default="build" basedir=".">
<target name="build"/>
<target name="clean"/>
</project>
To create the project, from within NetBeans, choose File->New Project, and choose a "Java Project with Existing Ant Script" within the General category. In the next wizard panel, select as location the project's directory, e.g. [It may seem superfluous to create an empty source directory and empty build targets, but I discovered that without these, some actions in the IDE can have the side effect of removing the exported JAR definintions.] After the project is created, bring up the project's properties window, and choose Output. Here you will declare the JARs that this free-form project exports. Select all the JARs that you put into the library wrapper project directory. When later you declare a dependency on this project, these are the JARs that will be added to the class path. Here is what this step looks like for my first library, 01: ![]() And that's it! Now you are ready to declare project dependencies on your new library wrapper projects. Right-click on the Libraries node in the project logical view, and choose "Add Project...". Select the project directory. All JARs in the project will be added as dependencies. (2006-12-04 22:47:43.0) Permalink Comments [3] DataProvider component for internationalizing Creator applications The JavaServer Faces standard JSP tag library includes the In the meantime, I have put together a simple DataProvider component, PropertyResourceProvider, which plays the same role, but has much better design-time support. How to install the PropertyResourceProvider Download the PropertyResourceProvider complib to a local directory. From within Creator, open up Tools -> Component Library Manager, and click on "Import". Use the browse feature to locate the downloaded component library, and select it. The library contains a single component, PropertyResourceProvider, which you can import into its own category, or into a pre-existing category. How to use the PropertyResourceProvider A PropertyResourceProvider wraps a Java resource bundle file, and makes the keys in the bundle file appear as data fields. In general, you should use one PropertyResourceProvider per resource bundle file. The component has a single property, The overhead involved in creating a PropertyResourceProvider is minimal, so it is probably easiest to add them to each page on which they are needed. Localizable component values will need to be added to a resource bundle, instead of being set directly on the component. There are a number of ways of adding new keys to a resource bundle file. You can click on the file in the project view to edit it directly (look under the Source Packages node), or you open the file node and right click on a locale node to add key and value pairs, one by one. To bind a component to a localizable value, right-click on the component and choose "Bind to Data". Select the appropriate PropertyResourceProvider, and the keys currently defined in the resource file will appear as fields. Select a field, and Creator will set the property's value to an expression that binds to the selected field. Close the binding window, and you will see the property value appear in the designer. PropertyResourceProvide is just like any other DataProvider, so you can also edit property values in the component's properites sheet, or by choosing the "Property Bindings..." context menu item. The PropertyResourceProvider will automatically choose the correct bundle file to load based on the locale of the Faces context for each request. This locale is determined by examining the client locale of the incoming HTTP request, and the list of supported locales given in the application's faces-config file. Typically, adding a locale to a project involves two steps:
Hope this helps! (2006-08-23 15:36:49.0) Permalink Comments [4] Rough Guide: Editing Themes for Creator 2.0 The components that ship with Java Studio Creator 2.0 derive their look and feel, and in some cases, their behavior, from a theme. At the most basic level, a theme is simply a JAR file that contains resources such as CSS stylesheets and graphical icons. An easy way to create your own look and feel is to edit the contents of the default Creator theme. The following guidelines explain how to do it. A theme JAR file has three main types of content:
You'll find a copy of the default theme jar ( Expand the file into a new directory. Users of M$ Windows may find it more convenient to rename Step One: Updating the manifest The first thing to do is to give your theme a name, and to edit the manifest accordingly. I'll start by renaming the Creator default theme, from Here's the new manifest:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.6.2
Created-By: 1.4.2_07-b05 (Sun Microsystems Inc.)
Name: com/sun/rave/web/ui/theme/
X-SJWUIC-SWAED-Version: 3.0
X-SJWUIC-Theme-Version: 1.0
X-SJWUIC-Theme-Name: isopaleocopria
X-SJWUIC-Theme-Prefix: /theme
X-SJWUIC-Theme-Messages: org.isopaleocopria.themes.messages.messages
X-SJWUIC-Theme-Images: org.isopaleocopria.themes.properties.images
X-SJWUIC-Theme-JavaScript: org.isopaleocopria.themes.properties.javascript
X-SJWUIC-Theme-Stylesheets: org.isopaleocopria.themes.properties.stylesheets
A few important points about the manifest:
If the above conditions are not met, Creator will reject the theme. Nota Bene: According to the spec, lines in a JAR manifest file are limited to a maximum length of 72 bytes. When you extract and first open the manifest for editing, you may notice that some lines longer than 72 bytes have been wrapped, and the enjambed portion has been indented with a single space character. You'll need to patch these lines back together again before reconstituting the JAR or ZIP file. Step Two: Editing theme content Before editing the content, you'll want to move it to your own package. In order for the theme manager to find the content in its new location, you'll need to update the path values in the various property files listed above. For example, as part of developing my new theme I would move the Javascript file After updating the theme name and the locations of the property files, it's time to edit the theme content. In some cases, the key names in the property files will help you to identify which theme artifact belongs to which component. The CSS stylesheets also generally use a truncated version of the name of the component as the prefix of style class names that apply to the component. Step Three: Importing the edited theme into Creator When you are finished modifying the theme content, you will need to repackage the contents as a JAR or ZIP file which can then be imported into Creator. To import the theme file, start Creator and open or create a project. From the menu, open Tools -> Library Manager. Select the Theme Libraries section, and click on "New Library". Give the library a name, e.g. IsoPaleoCopria (note that spaces are not accepted, probably a bug), and add the theme JAR or ZIP file to the library's classpath and to its runtime, using the appropriate tabs. Finally, to apply the theme to the current project, select it in the project hierarchy, right-click, and choose "Apply Theme". Have fun! (2006-02-08 15:36:48.0) Permalink What, I wonder, were the deep thinkers at Fraters Libertas thinking? That a Latin motto is cool? Perhaps they are under the spell of their beloved leader's English malapropisms. If they are what I suspect they want to be - the brothers of liberty - their devise should read Fratri Libertatis. On the other hand, I think the pidgeon Latin better suits the general tenor of their political commentary. (2004-11-10 11:00:04.0) Permalink This is an actual piece of spam that was waiting for me in my inbox this morning. The English is priceless. I wish I knew the redactor's native language; "crave to feel crack" seems like a direct translation of some foreign idiom.
From: Candida Rebux
(2004-10-28 17:00:45.0)
Permalink
NetBeans 3.6 threw an IllegalStateException today while I was creating a new project. The exception was announced in a pop-up window, and also on the command line, with the message:
gris-118% sex exception: java.lang.IllegalStateException:
can't declare any more prefixes in this context
Perhaps it should try whispering them softly in my ear?
(2004-10-12 12:05:16.0)
Permalink
Comments [2]
There is a new website that aggregates RSS feeds from several bloggers well-known in the XML community, dubbed "Planet XMLhack": http://planet.xmlhack.com. (2004-10-01 10:22:48.0) Permalink Michael Sperberg-McQueen used to say that all markup is interpretation. And some markup is demonstration: </Bush>. I suppose I don't need to point out that the Bush element isn't well formed. Or that maybe it should be empty. (2004-09-26 18:46:45.0) Permalink Thanks to Gary Trudeau, I now know what "actually" means: Doonesbury. (2004-09-26 18:21:19.0) Permalink Sometimes a word describing a technique can take on localized forms, which effectively describe local variations in the technique. Take biscuit. The word comes to us from Latin via French, and means, literally, "twice baked". Baked goods were passed a second time through the oven to ensure their longevity. At the English table, it refers generally to savories; at the French, to sweets. Italy has given us a sweet variant, often with anise, that we have imported along with the Italian name for the technique: biscotto. And from Germany, that ultimate in crackers for teething babies, zwieback. These are baked once as bread, and then toasted. (2004-09-20 16:52:26.0) Permalink |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||