NLS enabled JHeadstart templates

2

JHeadstart is a great tool for generating ADF Faces applications. One of the main new features (since 10.1.3) is the templating mechanism. Almost everything is generated with velocity templates : pages, regions, the faces-config, managed beans definitions etc. (with the exception of the pagedefinition files that are generated with the JDeveloper extension mechanism). The neat thing is that you can easily change the default template for your own template to change the appearance or behaviour of some component, which is what we do quite extensively in our applications. In this way we are able to add post-generation changes to the generation process. In this post I will demonstrate how you can leverage your custom template and make them nls-enabled.

....

For example, somewhere in our application we have a copy button that makes a copy of the current item (e.g. Employee).
The easiest way to  go is to just add the exact JSF code to our template, like this : 

&nbsp; &lt;af:commandButton textAndAccessKey=&quot;Make a copy of this Employee&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id=&quot;EmployeeCopyButton&quot;&gt;<br />&nbsp; &lt;/af:commandButton&gt;<br /> 

NB For the sake of simplicity I’ll focus on the text and leave out all the other properties.
By the way, the copy button provides us with a little problem, because JHeadstart does not have a default copy button and a matching template. So you have to find a suitable template to add it to. I’ll not go into detail how you can do that, but refer to the JHeadstart Developer’s guide.

With this simple step we can be happy because the button is always generated and we don’t have our testers on our back because we forgot to add the button after the application generation. Although this may be enough in some cases, it is often not enough because it is not suited for a multi-lingual application. Fortunately, internationalization is a standard feature of JHeadstart. By default, for each language, an ApplicationResources.properties file is generated that contains the messages, lables, headings etc. of your application in a key-value manner. In a JSF page we can refer to the text with an EL-expression of the form #{nls[‘PROPERTY_KEY’]}. So instead of having the text in the template we manually add our text to the resources file(s) (COPY_BUTTON_LABEL_EMPLOYEE=Make a copy of this Employee) and change the template to:

&nbsp; &lt;af:commandButton textAndAccessKey=&quot;#{nls['COPY_BUTTON_LABEL_EMPLOYEE']}&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id=&quot;EmployeeCopyButton&quot;&gt;<br />&nbsp; &lt;/af:commandButton&gt;&nbsp; <br />

This is already an improvement, but still we have to make sure that, after generation, the message is added to the resource file(s) again. If only we could generate the entry in the resource file…

For this, we can use the same mechanism that the default velocity templates use to generate the text on buttons, tabs etc.; the JHS.nls (…) method. This method does a two things : 1) it adds a key-value entry in the resource properties file(s) and 2) it returns the nls enabled string (nls[COPY_BUTTON_LABEL_EMPLOYEE]}") that is used in the JSF property.
So now we change the template to  :

&nbsp; &lt;af:commandButton textAndAccessKey=&quot;${JHS.nls(&quot;Copy text&quot;, &quot;COPY_BUTTON_LABEL_EMPLOYEE&quot;, &quot;Make a copy of this Employee&quot; )}&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id=&quot;EmployeeCopyButton&quot;&gt;<br />&nbsp; &lt;/af:commandButton&gt;

This generates our entry in the resource file with the second parameter as the key and the third parameter as the value and returns our EL expression string.

In this case, the first parameter is not used. So why is it there?
So let’s make a sidestep. Maybe you’ve noticed, that many labels on generated pages are not just simple labels, but often contain a verb like ‘New Employee’ or are a bit more complicated like ‘Departments with this DepartmentId already exists’. In Dutch that would be : ‘Invoeren Employee’ and ‘Departments met deze DepartmentId bestaat reeds’. During the generation information from the application definition file is combined with standard text. You see it used everywhere in the standard velocity templates, for example in the newButton.vm template :
textAndAccessKey="${JHS.nls(${JHS.current.group.displayTitleSingular}, "NEW_BUTTON_LABEL_${JHS.current.group.name}", "NEW_BUTTON_LABEL" )}" that results in textAndAccessKey="#{nls[‘NEW_BUTTON_LABEL_EMPLOYEES’]}" on the JSF commandButton and the entry NEW_BUTTON_LABEL_EMPLOYEE=New Employee in the resource file.
The standard text, identified by the third parameter, is retrieved from the GeneratorText.properties file in the generator library (oracle.jheadstart.addins.jag.10.1.3.jar) and combined with the first parameter and then stored in the generated resource file with the second parameter as the key. In this example you’ll also notice the reference to properties in the application definition file : JHS.current.group.displayTitleSingular and JHS.current.group.name.

In the last stage we will improve our custom template and reference information in the application definition file :

&nbsp; &lt;af:commandButton textAndAccessKey=&quot;${JHS.nls(&quot;Copy button&quot;, &quot;COPY_BUTTON_LABEL_${JHS.current.group.name}&quot;, &quot;Make a copy of this ${JHS.current.group.displayTitleSingular}&quot; )}&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id=&quot;${JHS.current.group.name}CopyButton&quot;&gt;<br />&nbsp; &lt;/af:commandButton&gt;

Some text in our message is now retrieved from the group property ‘Display Title (Singular)’. We’ve also added the group name to the key and the component id to make them unique.

This is a nearly perfect solution. The only drawback is that we generate the same text for all languages and we have to manually change them. Fortunately, the application definition file has a setting that prevents the generator from overriding our message.

A definite solution would be to add our text to the GeneratorText properties files, but that would mean to change the JHeadstart generator library and I’m not too happy about that. I hope that we’ll be able to add or change the standard text with a future release of JHeadstart.

Resources

The JHeadstart Developer’s guide :
Internationalization : page 3-120
JHeadstart templates : page 3-99

Share.

About Author

Aino Andriessen is a consultant on Enterprise Java, ADF, PL/SQL, XML, and SOA development and is Expertise Lead on Application Lifecycle Management (ALM). He has a strong interest in ADF, SOA, Maven, architecture, quality management, delivery and application lifecycle management. Aino publishes on the AMIS technology blog and has been a presenter at the ODTUG Kaleidoscope, Oracle Open World and UKOUG TechEbs.

2 Comments

  1. Aino Andriessen on

    Hi,

    I am sorry but I cannot reproduce your errors. Always beware of copy and paste, maybe try manual entering the information.
    On which part do you get the errors?

    By the way, I discovered a slight error in the second piece of code; it should be textAndAccessKey=”#{nls[‘COPY_BUTTON_LABEL_EMPLOYEE’]}” , notice the ‘.
    I made this update in the text too.

    Ciao
    Aino

  2. Jheadstart Newbie on

    Hello Aino,

    I have been trying to use the NLS enabled template that are depicted in your blog.
    But compilation errors were raised from the following code :

    errors:
    Error(72,77): Whitespace required.
    Error(72,105): ‘=’ missing in attribute.
    Error(72,30): Attribute value should start with quote.

    Please Advise!!
    Best Regards,