views:

125

answers:

5

I'd like to enforce standardized keys by storing them as static final String variables on a Java class, and either referencing or statically importing them, to use them as values in either XML, Strings, Methods, Annotations, etc.

Does anyone know a good way to have Maven insert (like filtering) values like StringKeys.SOME_KEY into an XML file? e.g. something like

<element value="${StringKeys.SOME_KEY}"/>

or similar - the main idea is to enforce commonality and prevent key mis-alignment. Or an alternative solution to accomplish the same - with some semantic that if a non-existant String is referenced, that it fails during build? Bonus points if it works in C# as well.

+2  A: 

You can use XSLT and use EL expressions to expand strings.

Thorbjørn Ravn Andersen
True, do you know an easy way to hook that into a build or other process? (and *ideally* C# as well.
jayshao
The hard part is getting the object in. The Java call back mechanism is transformer specific (the java namespace e.g.).
Thorbjørn Ravn Andersen
Yeah, have used quite a bit of XSLT, overall, I think it's just too hard/much setup to be viable in this case.
jayshao
+1  A: 

Sometimes using string constants is more trouble than it is worth. And IMO, this is one such example.

But if you wish to pursue this, here are some ideas that may work for you:

  1. Use a Java DOM library to build the XML in memory, using the Java constants.

  2. Put the constants into a Properties object, then create an XML file template using Velocity, Freemarker or an equivalent Java compatible templating language that expands the properties values into the XML.

    2a. In some circumstances JSPs could be used instead of a generic Java-compatible templating language.

  3. Generate the XML with placeholders for the named constants, then use XSLT to replace the placeholders with the actual values.

But in each case, the steps you take in order to use the named constants leads to fragility in other areas, not to mention more code and extra processing. Which brings me back to my original point ...

EDIT I think that the real reason that there is no really good solution to this problem is that it is a really hard problem.

To illustrate, using JSPs to generate the XML (and discipline) would ensures that you only use valid Java constants, and is fail-fast with respect to the generated Java classes. However, the JSP approach does not guarantee that you generate well-formed XML.

The root of the problem is that you need the expressiveness of embedding Java constructs in XML templates, combined with static checking of the well-formedness of both the Java and the XML aspects of the templates. You really need proper linguistic support for this, but in reality the available solutions just output characters without regard for (in this case) XML syntax rules.

Stephen C
While I tend to agree with you if doing this from scratch, I was hoping someone already had a solid, fail-fast templating replacement that hooks into Maven - since this has burned us several times already
jayshao
A: 

Velocity or similar is your best bet, but it would require writing your own plugin.

I'd generally do this in the other direction - store the keys and values in a properties file and filter that into XML as well as reading them into the Java / C# class. You can find an example in the free sample chapter from our book: http://brettporter.wordpress.com/2009/09/30/apache-maven-2-effective-implementation-sample-chapter/

Brett Porter
So a properties file gets you DRY - how do you prevent pulling up a blank field from the property file though?
jayshao
I'm not exactly sure what you mean here. You want to be able to set default values that can be replaced?
Brett Porter
+1  A: 

Can't you use XML enumeration restriction of string?

<xsd:restriction base = "xsd:string">
  <xsd:enumeration value = "AUD"/><!-- Australian Dollar -->
  <xsd:enumeration value = "BRL"/><!-- Brazilian Real -->
  <xsd:enumeration value = "CAD"/><!-- Canadian Dollar -->
</xsd:restriction>
Fakrudeen
This doesn't really get me the same usage as static constant strings though - e.g. what I want is to use the compiler to test this for me and not get broken keys
jayshao
you can use xsd.exe [or JAXB in java] to generate this a C# [java] enumeration.
Fakrudeen
+1  A: 

You can use Xslt to generate your POM , probably to refer you can use the below

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:dyn="http://exslt.org/dynamic" extension-element-prefixes="dyn"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"  xmlns:masterrule="com.Xxxxxx.ClassName" exclude-result-prefixes="masterrule #default">

<xsl:value-of select="masterrule:xxxxx"/>
srinannapa
this looks promising (though not sure I'd use it for the POM, more likely for the XML config file we're trying to generate, per the question above) - have a URL with more samples?
jayshao