Monday, March 23, 2009

Perils of (Ab)using the java.ext.dirs Property

I frequently use the java.ext.dirs system property as a shortcut for setting the classpath for a command-line Java program, i.e.:

java -Djava.ext.dirs=lib com.scottmcmaster365.MyMainProgram

No, this isn't great for production use, but for quick-and-dirty testing, it's much more convenient than creating a launcher batch file / shell script or manually typing a ginormous claspath.

Well, this practice jumped up and bit me the other day. After the requisite amount of pain and suffering, I observed that setting java.ext.dirs does not extend but rather overrides the real optional-extension location (at least with Sun's JVM), as sort-of-alluded-to here. As a consequence in this situation, Java will, at runtime, lose track of your optional packages. In my case, this manifested itself as an inability to load the JCA crypto providers (i.e. ClassNotFoundException).

If you're not using any of the standard optional packages, setting your own extensions path doesn't seem to matter. But I guess the moral of the story is that you shouldn't count on the extension mechanism to stand in for the classpath mechanism, even in all expedient situations.

Wednesday, March 11, 2009

Generating Strongly-Typed Properties Classes With openArchitectureWare, Part 4: Generating Java Classes

In the fourth part of this series, I'm finally read to generate strongly-typed wrappers for Java .properties files. If you would like to review how I got to this point, check out the earlier installments here, here, and here.

First, a little bit about my code generation philosophy. I prefer to only generate specializations -- the things that will actually vary from model to model -- when possible. Inheritance works well for this: I can put common functionality in base classes and generate subclasses. This cuts down on the amount of code that I have to work with in the template. As an added bonus, the base class can be tested (and perhaps even used) independently of the code generation process.

With that in mind, I will start by creating base classes. Recall that my PropertySet is defined as supporting two different "load types" -- resource bundle and classloader resource. That means two base classes, which I will call ResourceBundleProperties and ClassLoaderResourceProperties. Since my goal is to demonstrate openArchitectureWare, model-driven development, and code generation, and not to write the be-all-and-end-all of .properties file loaders, this code won't support everything you can imagine. Generally speaking, I'm following the tried-and-true approaches described here.

ResourceBundleProperties.java

package com.scottmcmaster365.properties;

import java.util.Properties;

/**
 * Load a properties file from a resource bundle
 * following the approach described here:
 *  http://www.javaworld.com/javaworld/javaqa/2003-08/01-qa-0808-property.html?page=2
 * @author scottmcm
 *
 */
public class ResourceBundleProperties
{
 protected java.util.Properties properties;
 
 /**
  * Load the properties from the resource bundle with the given name.
  * @param name
  */
 public ResourceBundleProperties(String name)
 {
  ClassLoader loader = Thread.currentThread ().getContextClassLoader();

  final java.util.ResourceBundle rb = java.util.ResourceBundle
    .getBundle(name, java.util.Locale.getDefault(), loader);

  properties = new java.util.Properties();
  for (java.util.Enumeration<String> keys = rb.getKeys(); keys
    .hasMoreElements();) {
   final String key = (String) keys.nextElement();
   final String value = rb.getString(key);

   properties.put(key, value);
  } 
  
  if (properties == null) {
   throw new IllegalArgumentException("Could not load " + name + " as resource bundle");
  }
 }
 
 public Properties getProperties() {
  return properties;
 }
}


ClassLoaderResourceProperties.java

package com.scottmcmaster365.properties;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
 * Load a properties file from a resource bundle
 * following the approach described here:
 *  http://www.javaworld.com/javaworld/javaqa/2003-08/01-qa-0808-property.html?page=2
 * @author scottmcm
 *
 */
public class ClassLoaderResourceProperties
{
 protected java.util.Properties properties;
 
 private static final String SUFFIX = ".properties";

 /**
  * Load the properties from the resource bundle with the given name.
  * @param name
  * @throws IOException 
  */
 public ClassLoaderResourceProperties(String name) throws IOException
 {
  ClassLoader loader = Thread.currentThread ().getContextClassLoader();

  InputStream in = null;
  try {
   if (!name.endsWith(SUFFIX)) {
    name = name.concat(SUFFIX);
   }

   in = loader.getResourceAsStream(name);
   if (in != null) {
    properties = new java.util.Properties();
    properties.load(in);
   }
  } finally {
   if (in != null)
    try {
     in.close();
    } catch (Throwable ignore) {
    }
  }
  
  if (properties == null) {
   throw new IllegalArgumentException("Could not load " + name + " as classloader resource");
  }
 }
 
 public Properties getProperties() {
  return properties;
 }
}


Next I create a code generation template (an .xpt file, written in the oAW Xpand template language) to create a subclass based on the information in PropertySet models.

JavaWrapperTemplate.xpt

«IMPORT metamodel»

«DEFINE javaClass FOR properties::PropertySet»
 «FILE Package.replaceAll("\\.", "/") + "/" + Name + ".java"»
  package «Package»;
  
  /**
   * Load a properties file based on the approach described here:
   *   http://www.javaworld.com/javaworld/javaqa/2003-08/01-qa-0808-property.html?page=2
   */
  public class «Name-»
  «IF LoadAs == properties::LoadType::CLASSLOADER_RESOURCE-»
   extends com.scottmcmaster365.properties.ClassLoaderResourceProperties
  «ELSE-»
   extends com.scottmcmaster365.properties.ResourceBundleProperties
  «ENDIF-»
  {
   public «Name»() 
    «IF LoadAs == properties::LoadType::CLASSLOADER_RESOURCE»
     throws java.io.IOException
    «ENDIF»
   {
    super("«ResourceName»");
   }
   
   «EXPAND property FOREACH Properties»
   «EXPAND propertyWithDefault FOREACH Properties»
  }
 «ENDFILE»
«ENDDEFINE»

«DEFINE property FOR properties::Property»
 public «Type» get«Name»() {
  «IF Type == properties::PropertyType::Integer»
   return Integer.parseInt(properties.getProperty("«Name»"));
  «ELSE»
   return properties.getProperty("«Name»");
  «ENDIF»
 }
«ENDDEFINE»

«DEFINE propertyWithDefault FOR properties::Property»
 public «Type» get«Name»(String defaultValue) {
  «IF Type == properties::PropertyType::Integer»
   return Integer.parseInt(properties.getProperty("«Name»", defaultValue));
  «ELSE»
   return properties.getProperty("«Name»", defaultValue);
  «ENDIF»
 }
«ENDDEFINE»

While not quite as simple as the template I presented last time to generate sample .properties file, this is still pretty straightforward. Notice how I determine which base class to extend using the value of LoadAs defined in the input model. The last two Xpand templates for Property generate overloaded getProperty() methods, with and without the default value.

Before I can use this template, I need to wire it into my oAW workflow. So I make the following addition to generator.oaw, right after checking the model with the .chk file:
<!--  generate code -->
<component class="org.openarchitectureware.xpand2.Generator">
 <metaModel idRef="mm"/>
 <expand
  value="template::JavaWrapperTemplate::javaClass FOR model" />
 <outlet path="${src-gen}" >
  <postprocessor class="org.openarchitectureware.xpand2.output.JavaBeautifier" />
 </outlet>
</component>


Now when I invoke generator.oaw as an oAW workflow using my sample PropertySet model, I get the following code generated into my project's src-gen directory:

MyProperties.java

package com.scottmcmaster365.propertiessample;

/**
 * Load a properties file based on the approach described here:
 *   http://www.javaworld.com/javaworld/javaqa/2003-08/01-qa-0808-property.html?page=2
 */
public class MyProperties
  extends
   com.scottmcmaster365.properties.ClassLoaderResourceProperties {
 public MyProperties()

 throws java.io.IOException

 {
  super("MyProperties.properties");
 }

 public Integer getMyIntegerProperty() {

  return Integer.parseInt(properties.getProperty("MyIntegerProperty"));

 }

 public String getMyStringProperty() {

  return properties.getProperty("MyStringProperty");

 }

 public Integer getMyIntegerProperty(String defaultValue) {

  return Integer.parseInt(properties.getProperty("MyIntegerProperty",
    defaultValue));

 }

 public String getMyStringProperty(String defaultValue) {

  return properties.getProperty("MyStringProperty", defaultValue);

 }

}

The benefit of having a strongly-typed wrapper can be seen in this unit test example:
@Test
public void testLoadMyProperties() throws IOException
{
 MyProperties properties = new MyProperties();
 assertEquals(2, properties.getMyIntegerProperty());
 assertEquals("hello world", properties.getMyStringProperty());
}


And that's just about it. If I want to use my new properties wrapper in a real project, I will need to pull in all of the files from this project and add some sort of "generate" target to my Ant build which uses the oAW Ant task to invoke generator.oaw.

I should point out that there is a notable overhead involved in spinning up the oAW code generation pipeline, and if you have to do it multiple times per build, your build process can slow down considerably. It is therefore beneficial to consolidate into as few model files (.xmi's) as possible. So a possible enhancement to what I have done here would be to metamodel a class which is a set of PropertySets and then enhance my Xpand templates to generate multiple files, so that I can cram more than one PropertySet into a model.

I hope that after reading this series, you're ready to run out and EMF, oAW, modeling, and code generation. If you do, please share your experiences with me, because I'm always looking out for new techniques and best practices.

Tuesday, March 10, 2009

Generating Strongly-Typed Properties Classes With openArchitectureWare, Part 3: Checks, Workflow, and a Template

Last time I created a sample model using the Properties metamodel that I built in the first post of this series. Now I'm going to put it all together and actually generate something with openArchitectureWare -- not Java code just yet, but rather, a sample .properties file which can be customized and loaded using the Java code that I'll create in the next entry.

Checks
openArchitectureWare provides Check constraints for validating models. For the Properties scheme that I have designed, it makes sense to require models to conform to three constraints:
  1. PropertySet must have a name. I will use this to generate the Java class name.
  2. PropertySet must have a resource name. This will tell me what file to load at runtime.
  3. Properties must have a name. This one is pretty obvious.
Here is how to encode these rules in the Check language (file Checks.chk):
import Properties;

context properties::PropertySet ERROR "PropertySet must have a name" :
Name != null && Name.length > 0;

context properties::PropertySet ERROR "PropertySet must have a resource name" :
ResourceName != null && ResourceName.length > 0;


context properties::Property ERROR "Properties must have a name" : Name != null && Name.length > 0;
The "import" line pulls in the Properties metamodel. Marking these constraints as "ERROR" stops oAW processing with the specified message when such a condition is encountered. The rest of the code is pretty intuitive. Later, when I talk about oAW Workflows, you'll see how this gets wired into the generation process.

Simple Template
It's time to write an oAW template to generate a sample .properties file. This is done with the oAW Xpand language, whose most visible feature is the cute little «chevrons» that mark off the directives. I won't attempt to detail the features of Xpand, but rather point you to the documentation. Suffice to say that it's very easy to get started. Here is a template (PropertiesFileTemplate.xpt) that generates a .properties file from a model:
«IMPORT metamodel»

«DEFINE propertiesFile FOR properties::PropertySet»
«FILE ResourceName + ".SAMPLE"»
«EXPAND property FOREACH Properties-»
«ENDFILE»
«ENDDEFINE»

«DEFINE property FOR properties::Property»
«Name» = «DefaultValue-»
«ENDDEFINE»
When I finally run this in the next section, it will generate a file in .properties format with each property in the model. The file is named based on the value of the ResourceName attribute of the PropertySet. It is suffixed with ".SAMPLE" because presumably it would be customized in a real application. In my next post, I'll use Xpand to achieve the ultimate goal of this project, namely, to generate some Java code to load and wrap these properties. First, though, I need to tie everything together so that the oAW generator can run.

Workflow
"Workflows" are essentially build scripts for openArchitectureWare-based artifacts. They generally end with an extention of ".oaw", and they can be launched directly from Eclipse in an openArchitectureWare project using a "Run As | openArchitectureWare Workflow" context menu item. There are a handful of things that you can do in a workflow, but in my experience, they tend to be pretty boilerplate. Here is one (generator.oaw) that runs Checks and invokes the generator on the PropertiesFileTemplate for our model:
<?xml version="1.0"?>
<workflow>
 <property name="model" value="PropertiesGenerator/src/SamplePropertySet.xmi" />
 <property name="src-gen" value="src-gen" />
 
 <!-- set up EMF for standalone execution -->
 <bean class="org.eclipse.mwe.emf.StandaloneSetup" >
  <platformUri value=".."/>
 </bean>

 <!-- load model and store it in slot 'model' -->
 <component class="org.eclipse.mwe.emf.Reader">
  <uri value="platform:/resource/${model}" />
  <modelSlot value="model" />
 </component>

 <!-- check model -->
 <component class="oaw.check.CheckComponent">
  <metaModel id="mm"
   class="org.eclipse.m2t.type.emf.EmfRegistryMetaModel"/>
  <checkFile value="metamodel::Checks" />
  <emfAllChildrenSlot value="model" />
 </component>

 <!--  generate sample .properties file -->
 <component class="org.openarchitectureware.xpand2.Generator">
  <metaModel idRef="mm"/>
  <expand
   value="template::PropertiesFileTemplate::propertiesFile FOR model" />
  <outlet path="." />
 </component>
</workflow>
In a more serious implementation, the execution of the .oaw file would be integrated in an Ant build using oAW's custom Ant task. For this project, I'll just use the oAW Eclipse runner.

The model to work with is declared as a property at the top of the file. The key sections are the last two -- "check model" and "generate sample .properties file". The only potentially-tricky part is getting the package references right. So here is a snapshot of my project for you to compare to:



Now I actually have a working code generation pipeline set up. To conclude in my next post, I'll write a slightly more sophisticated template to generate Java code, and maybe talk a little bit about code generation philosophy.

Sunday, March 1, 2009

Generating Strongly-Typed Properties Classes With openArchitectureWare, Part 2: Model

Previously I demonstrated how to create an Ecore metamodel describing Java .properties files, with the ultimate goal of using openArchitectureWare to build strongly-typed accessor classes for my properties. Before I start writing oAW templates, though, I want to have a sample model that I can work with which is relatively simple but still exercises most of the breadth of my metamodel.

The oAW sample project contains a model already called "Model.xmi". The "xmi" is "XML Metadata Interchange", an OMG specification concerned with interoperable models, and the default format for models in Ecore/EMF. I will delete the existing Model.xmi file and create a new model called "SamplePropertySet.xmi". One way to do this is to open the Properties.ecore metamodel, right-click on the class that I want at the "root" of my model (namely, PropertySet), and select "Create Dynamic Instance". Choosing a location in my workspace, away I go.

The .xmi file can be edited with the "Sample Reflective Ecore Model Editor", which is essentially the same as the tree-node-properties editor I used on the .ecore file, except now the entities that I edit on my model are instances of the classes and attributes defined in my metamodel. In other words, the "root" of my model is a PropertySet, and to that I can add children which are Property instances. When I select one of these and open the Eclipse Properties grid, the properties are the class attributes defined in the metamodel. If you have been following along and are still a little fuzzy on the relationship between metamodel and model, the following illustration might be helpful:



I'm going to test my openArchitectureWare code generation templates with a couple of properties -- one of type "Integer" and another of type "String". My "completed" model looks like this:



There are a number of other things that I could do with EMF at this point, such as generating a Java object model and "starter" Eclipse plugins for working with my models. But I don't need to do any of that for this project: Starting next time, everything going forward will be in the Land of openArchitectureWare.

Generating Strongly-Typed Properties Classes With openArchitectureWare, Part 1 Addendum: Graphical Ecore Editor

Last time I showed how to build an Ecore metamodel in Eclipse using the Sample Ecore Model Editor. Ed Merks from the EMF team (whose EMF book is out in a new edition, by the way) commented that I could be using the Graphical Ecore Editor, which is a part of the Ecore Tools subproject. He is absolutely correct. (Thanks Ed.) There are a couple of steps to go through to do that, so I'll talk about those here.

First, you need to install the Ecore Tools package, which you can find on the Ganymede Update Site (assuming you're using Eclipse 3.4) under "Models and Model Development". After you do that, you can select File | New | Other in Eclipse, and there will be an "Ecore Tools" folder available. Underneath that, choose "Ecore Diagram". A wizard appears, and you can select your .ecore file as the domain model.

This will add a file to your project which has the extension ".ecorediag", and when you open it up, you'll get a Rose-like boxes-lines-and-properties editor which is far more user-friendly than the sample editor. Here is what my Properties Generator metamodel looks like in diagram form after some slight rearrangement: