Monday, May 18, 2015

ADF BC i18n - Text Translation

A common request on web applications is internationalization (i18n), specially the translation of text and data. In this post we are going to see how you can work with text translation within the ADF BC module of an ADF application and how to avoid common pitfalls.

The samples showed in this post are based on the HR schema, specifically, on the Regions table.

In order to provide text translation we first configure the ADF BC project Resource Bundle: Right click on project -> Project Properties



From the above image:
  • Automatically Synchronize Bundle: Select to automatically create text resources in the resource bundle when editing UI components in the visual editor.
  • Warn About Hard-coded Translatable Strings: Select to display a message when a UI component being edited in the visual editor has an associated translatable string.
  • One Bundle Per Project or Per File: This configuration depends on your project. I like one bundle per project because most of my projects are developed in modules and every module is small, so one bundle is enough.
  • Resource Bundle Type: Properties Bundle is perhaps the most common type. List Resource Bundle may be difficult to edit and may cause problems when you have a lot of translatable text. Xliff is only important if you are using the same type in other Oracle applications.
After you are done with the previous configuration, you can create your Entities, View Objects, Properties Sets... etc. And when you edit a translatable text, it will be added automatically to the resource bundle.

Lets create an Entity based on the Regions table and add a new column called Description of type String:



Lets modify the Control Hints of each attribute, specifically, lets change the Label Text property. Here we are using the Spanish translation for the name attribute of a region:



After doing this for each attribute, we can inspect the entity's XML source code and notice the following:

1. The attribute definition now has a Properties section where the key identifier for the attribute in the resource bundle is defined:



2. Also, at the end of the XML file, the Entity's resource bundle definition is defined:



If we open the above mentioned resource bundle file, we'll see something similar to this (we have added the Description_TXT key for later use):



Now that we have a base resource bundle, lets create the English translation. Right click on the container package of our resource bundle and select New, in the popup under General, select File. Enter the same base name of our resource bundle and append an underscore and the code of the target language, in this case English is en. Copy the same keys but provide the text translated to English:



Recommendation: If you are going to edit the resource bundle files, try to do it using JDeveloper option Edit Resource Bundles... under Application menu, since some characters are written to the file in UNICODE. For example, you can see that in ModelBundle.properties Spanish accents and special characters are written in UNICODE.



We can be more specific, for example, we can have a file for US English (ModelBundle_en_US.properties) and a file for UK English (ModelBundle_en_UK.properties) but the general one works for now.

Lets test what we have done so far. Create a default view object for the Regions entity and add it to an Application Module, then run the Application Module. Follow my previous post about the ADF BC Tester Locale Configuration if you want to be able to change the language from the ADF BC Tester application.





You can notice that when we change the locale, the Label Text property of each attribute changes properly.

Now lets try something more programmatic. Lets return the text for the Description attribute from our resource bundle. Open the Regions entity and under the Java section, click on the pencil icon and select the Generate Entity Object Class option and the Accessors option:



This will create the RegionsImpl class where we can modify the text for the Description attribute. In the RegionsImpl class, modify the getDescription method to one of the following


1. Use the oracle.jbo.common.StringManager to access to a hardcoded resource bundle:
...
//In RegionsImpl

    /**
     * Gets the attribute value for Description, using the alias name Description.
     * @return the Description
     */
    public String getDescription() {
        Locale locale = getDBTransaction().getSession().getLocale();
        return StringManager.getLocalizedString("com.javanme.model.res.ModelBundle",
                                                "Description_TXT", 
                                                null,
                                                locale,
                                                null, 
                                                false);
    }
...


2. Use the oracle.jbo.common.StringManager class using the resource bundle definition of the Entity/ViewObject:
...
//In RegionsImpl

    /**
     * Gets the attribute value for Description, using the alias name Description.
     * @return the Description
     */
    public String getDescription() {
        Locale locale = getDBTransaction().getSession().getLocale();
        return StringManager.
               getLocalizedStringFromResourceDef(getResourceBundleDef(),
                                                 "Description_TXT",
                                                 null,
                                                 locale,
                                                 null, 
                                                 false);
    }
...


3. Use the java.util.ResourceBundle class to access to a hardcoded resource bundle:
...
//In RegionsImpl

    /**
     * Gets the attribute value for Description, using the alias name Description.
     * @return the Description
     */
    public String getDescription() {
        
        ResourceBundle res =
            ResourceBundle.getBundle("com.javanme.model.res.ModelBundle",
                                     getDBTransaction().getSession().getLocale());
        return res.getString("Description_TXT");
        
    }
...


Using any of the above, we'll get the translated text for the Description attribute:





Following are my notes about the above strategies:

Strategy 1
Uses the locale of the current DB Transaction. This is how you access the current locale in ADF BC without breaking the MVC architecture. Then uses the class oracle.jbo.common.StringManager, which is a singleton, in order to get a localized String from a Resource Bundle. Notice that this strategy uses a hardcoded resource bundle. I'd use this strategy if the Entity/ViewObject does not have defined a resource bundle in its XML file.
You can learn more about the StringManager class in the API docs.

Strategy 2
Uses the locale of the current DB Transaction. This is how you access the current locale in ADF BC without breaking the MVC architecture. Then uses a class oracle.jbo.common.StringManager, which is a singleton, in order to get a localized String from the resource bundle defined in the XML file of the Entity/ViewObject. I'd use this strategy if the Entity/ViewObject does have defined a resource bundle in its XML file. This is my preferred strategy.
You can learn more about the StringManager class in the API docs.

Strategy 3
Uses the locale of the current DB Transaction. This is how you access the current locale in ADF BC without breaking the MVC architecture. Then uses the class java.util.ResourceBundle in order to get a localized String. Notice that this strategy uses a hardcoded resource bundle. I would not use this strategy in ADF BC since it requires an extra configuration step which will be discussed in a moment.

Strategies 1 and 2 are almost the same, the only difference is that one of them (2) uses the definition of the Entity's or ViewObject's resource bundle. 
They both make use of the oracle.jbo.common.StringManager class, a singleton, for accessing localized Strings. Don't be afraid to use this class in your accessors methods, it won't create more than one instance and it will take care of the default locale of the JVM (this is really important! as we'll see next). Being part of the ADF framework, this is what the framework uses and recommends.

Strategy 3 is a tricky one and it will look OK if we test it from the ADF BC Tester, but it may not work properly (I mean it won't localize our text properly) if, for example, we run an ADF Faces page that access our Regions Entity/ViewObject.
If a resource bundle for the specified Locale does not exist, getBundle tries to find the closest match. In our example, if we are looking for the English translation (ModelBundle_en.properties) and the default locale (Locale.getDefault()) is es_CO getBundle will look for the resources in the following order:
  • ModelBundle_en.properties -> Because this is what we are looking for -> Found!!
  • ModelBundle_es_CO.properties -> Because this is Locale.getDefault()
  • ModelBundle_es.properties -> Variant of Locale.getDefault()
  • ModelBundle.properties -> When none of the above are found

The above will work properly and the correct ModelBundle_en.properties file will be read. Now let's try this: We need the Spanish translation (ModelBundle.properties in our example) and Locale.getDefault() returns en_US, getBundle will look for the resources in the following order:
  • ModelBundle_es.properties  -> Because this is what we are looking for -> Not Found!
  • ModelBundle_en_US.properties -> Because this is Locale.getDefault() -> Not Found!
  • ModelBundle_en.properties -> Variant of Locale.getDefault() -> Found!!
  • ModelBundle.properties -> When none of the above are found

You can notice that the java.util.ResourceBundle class won't get my ModelBundle.properties file but the ModelBundle_en.properties file, because the latter is found first.

This is why it is so tricky, if you don't have your resources named accordingly to their languages or if the JVM default locale (Locale.getDefault()) is different than your default language, it may not work properly. This is a common pitfall...

So after all this, I hope you consider using the oracle.jbo.common.StringManager class over the java.util.ResourceBundle class when working with resource bundles in your ADF applications.

see ya!


References


About the ResourceBundle Class. Oracle [online].
Available on Internet: https://docs.oracle.com/javase/tutorial/i18n/resbundle/concept.html
[accessed on May 17 2015].

Class StringManager. Oracle [online].
Available on Internet: https://docs.oracle.com/cd/E28389_01/apirefs.1111/e10653/oracle/jbo/common/StringManager.html
[accessed on May 16 2015].

Binaries. Jobinesh's blog [online].
Available on Internet: http://www.jobinesh.com/2010/06/accessing-resource-bundle-from.html
[accessed on May 14 2015].

Wednesday, May 6, 2015

International Day against DRM @PacktPub

Just a quick post with a great offer from Packt Publishing:

Today only! May 6th 2015, Packt Publishing is celebrating International Day against DRM and is offering all eBooks and Videos for $10

More info: http://bit.ly/1AEzH2k


Go get yours!




Thursday, April 30, 2015

ADF BC Tester Locale Configuration

Hi everyone. This is just a small post about how you can add more locales to the ADF BC tester in order to try your i18n at this layer. It's just about configuration (works on 11g and 12c), therefore, if you are interested in how to develop i18n for your ADF BC layer, you should wait for read my next post.

ADF BC Tester is a great tool which allows us to test our ADF BC layer before we move to the ADF Faces layer, this is important since it will help us identify possible bugs in the right layer. By default the tester will launch in the locale defined for your application module:



If you run the tester using the default configuration, you will end up with something like this:



But if we want to try a different locale for your ADF BC layer, we need to change the application module locale configuration (shown above) before running the tester. However, this is not a good practice. The ADF BC Tester can be configured to show a menu with different locales to be used.
In JDeveloper, go to Tools->Preferences->ADF Business Components->Tester:



Add as many locales as you want and once you run your ADF BC Tester again, you will notice the new menu with the selected locales:






see ya!

Monday, April 13, 2015

Java SE 7 End of Public Updates

Oracle has announced the last public release of JDK 7 to be delivered on April 2015.

This means that any security and bug fixes won't be available for public download but for Oracle customers only. You can, of course, download JDK 7 always, but the version you download after April 2015 won't have any new security or bug fixes.
 
If you have applications developed with JDK 7 you can:
  1. Buy a commercial support of Java SE to become an Oracle customer.  You will keep getting updates of JDK 7 and several other benefits.
  2. Migrate to Java SE 8 and keep getting public updates of JDK 8 until 2017
  3. Do nothing... Your applications will continue to work as they do today (if run on JDK 7), but of course, there are security and performance risks.

More info can be found in this link and on the following video:





See ya!

Friday, March 27, 2015

Custom fonts in ADF 11g

There are beautiful fonts you may want to use in your web applications. In this post I'm going to show you how you can use custom fonts such as Google Fonts in your ADF 11g Applications. For ADF 12c Applications, you can find more instructions here.

What you need

For JDeveloper 11gR1 you should download the ADF Skin Editor (download the latest release) since this version doesn't come with that tool integrated to the IDE. On the other hand, 11gR2 has the ADF Skin Editor tool integrated to JDeveloper.

As a best practice you should create your own skin based on a skin provided by Oracle. That way, whenever you want to change the font of your entire application, there is only one place to make the change: the custom skin. This post is based on this best practice, so make sure you understand how to work with ADF skins.

This is the font family we are going to use in this post. It's called Indie Flower

Since ADF 11g skins make use of CSS2, the process of using custom fonts is not as easier as in 12c, but we have a workaround for that, just make sure you use a custom skin and a page template on your application.


Custom fonts in ADF 11gR1 and 11gR2
If you are using 11gR1, create the skin application using the skin editor. Steps are as follows (Remember, if you are using 11gR2 you can create the skin from within JDeveloper):
Click on new application... Set the name and folder...
Set the skin project name and the target application release that you want to skin:



Then, create a new ADF Skin File (right click on project and select Create new ADF Skin File)



Extend whichever Oracle skin you want, JDeveloper will suggest you one if you like. When the Skin Editor opens, go to Selectors and expand the Global Selector Aliases node and then Font, there you can see the class ADFDefaultFontFamily which is where we need to make the change in order to set the new font family for our entire ADF Application. Go to the Properties Inspector and make the change in the Font Family property:






That's it, we have defined that all the components in an ADF application that uses this skin will use the custom font (except for those defined with a specific inlineStyle). However, if you notice we haven't told the skin file where the custom font is, that's because skins in 11g use CSS2 and so we can't define nor import the font in the skin file, if we do, it will get removed at runtime. The downside of this is that we can't use the skin editor to preview the font family change.

If you are using ADF 11gR1, deploy the custom skin as an adfLib (right click on project -> deploy...) and import it into your ADF application.
If you are using ADF 11gR2, this is not necessary since you can create the custom skin from within your project in JDeveloper.
Anyway, remember to change the {WEB-INF}/trinidad-config.xml file to make use of your custom skin:

...
  <skin-family>custom-skin</skin-family>
  <skin-version>default</skin-version>
...


The second part of the solution requires the use of Page templates, if you are not using page templates in your application, you will have to modify every single page where you want to use the custom font. The code you add to your page template or to your single page is the same:

<af:resource type="css" source="http://fonts.googleapis.com/css?family=Indie+Flower"/>


Here, we are adding a CSS resource where the custom font is defined. You may wonder where have the URL come from, well if you go to the Indie Flower font quick use, you will notice the URL is there.

Wondering where to place the above code? If you are using page templates, place it right after the jsp:root tag, on the other hand, if you are using single pages, place it inside the document tag.

Now, if you run an ADF application that makes use of your custom skin, all your components will be using the same font-family:


Before using custom fonts

After using custom fonts



You should be aware that if you have components that set the font-family in the inlineStyle property or use any other custom class that overrides the font-family, then those components won't use the font-family defined in the skin.

That's it, hopefully you now will be able to modernize your ADF 11g applications using new custom fonts.

see ya!

Saturday, March 21, 2015

Custom fonts in ADF 12c

There are beautiful fonts you may want to use in your web applications. In this post I'm going to show you how you can use custom fonts such as Google Fonts in your ADF 12c Applications. For ADF 11g Applications, you can find more instructions here.

What you need

As a best practice you should create your own skin based on a skin provided by Oracle. That way, whenever you want to change the font of your entire application, there is only one place to make the change: the custom skin. This post is based on this best practice, so make sure you understand how to work with ADF skins.

This is the font family we are going to use in this post. It's called Indie Flower

Since ADF 12c makes use of CSS3, the process of using custom fonts is simpler than it was in 11g.

Custom fonts in ADF 12c
Create your skin if you have not created one yet. In JDeveloper 12c you can use the integrated ADF Skin Editor tool as follows:




Extend whichever Oracle skin you want, JDeveloper will suggest you one if you like. When the Skin Editor opens, go to Selectors and expand the Global Selector Aliases node and then Font, there you can see the class ADFDefaultFontFamily which is where we need to make the change in order to set the new font family for our entire ADF 12c Application. Go to the Properties Inspector and make the change in the Font Family property:






Then, open the Source editor (next tab after Selectors) because we need to define the custom font. The following shows you an excerpt of the Skin CSS where we have defined the font and overridden the font-family property of the  ADFDefaultFontFamily class

...

@font-face {
  font-family: 'Indie Flower';
  font-style: normal;
  font-weight: 400;
  src: local('Indie Flower'), local('IndieFlower'), url(http://fonts.gstatic.com/s/indieflower/v7/10JVD_humAd5zP2yrFqw6ugdm0LZdjqr5-oayXSOefg.woff2) format('woff2'), url(http://fonts.gstatic.com/s/indieflower/v7/10JVD_humAd5zP2yrFqw6nhCUOGz7vYGh680lGh-uXM.woff) format('woff');
}

.AFDefaultFontFamily:alias {
    font-family: 'Indie Flower', cursive;
}

...


You may wonder where have the @font-face instruction come from, well if you go to the Indie Flower font quick use, you will notice there is the following link:

http://fonts.googleapis.com/css?family=Indie+Flower

If you open it, you will find the @font-face definition that you need to use in your Skin CSS. In the same quick use link you will find several ways to use the font: using a link, using an @import instruction and even suing JavaScript. However, only copying the @font-face instruction in the Skin CSS worked for me.

ADF Skin Editor 12c comes with a handy option where you can launch your browser and check the changes you have made to the skin without launching Weblogic or your ADF application:



Let's see how this works before and after changing the font-family:

Before using custom fonts
After using custom fonts


Now, if you run an ADF 12c application that makes use of your custom skin, all your components will be using the same font-family:


Before using custom fonts

After using custom fonts



You should be aware that if you have components that set the font-family in the inlineStyle property or use any other custom class that overrides the font-family, then those components won't use the font-family defined in the skin.

That's it, hopefully you now will be able to modernize your ADF 12c applications using new custom fonts.

see ya!

Should I commit .adfc_diagram files?

Wondering whether you should commit *.adfc_diagram files?
You should know that JDeveloper saves the position in the diagram of each component in these files, so if your diagram looks like this:



And if you don't commit these files, next time you checkout/clone from your version control system, it may look like the following, since JDeveloper will create a new file with default positions:



Each task flow has its own file, and the name for these files follows this pattern:

{TASK_FLOW_ID}.adfc_diagram

Where {TASK_FLOW_ID} is the task flow id you defined for the task flow when you created it. Now, if you want to know where is JDeveloper saving these files, you can go to Project Properties -> Project Source Paths -> Modelers:



Further more, if you want to know/change the directory where JDeveloper saves theses files inside your project, go to Application -> Default Project Properties -> Project Source Paths -> Modelers:



see ya!

Tuesday, January 6, 2015

Book Review: Mastering JavaServer Faces 2.2

Book cover from
http://www.packtpub.com
Java EE 7 is the latest version of the Java Enterprise platform. Lots of new features and three objectives: Developer productivity, HTML5 and Enterprise Demands.

In this post, I'll be reviewing the book "Mastering JavaServer Faces 2.2" written by Anghel Leonard and published by PACKT. As many others Packt titles, the chapters are easy to read, they follow a tutorial approach and a summary at the end.

I think this book is good for new and experienced Java EE developers. If you are a beginner, this book will teach you what you need to know about JSF to start your next project.
On the other hand, if you are an experienced Java EE developer you will find this book very easy to read. Just focus on the new features of the specification and you'll get updated to the latest version of JSF in a fast paced.

What I liked about the book:

  • Easy to read.
  • As an experienced Java EE developer it was easy to focus just on the new features.
  • Sample code is available to be downloaded from Packt's website and it is well organized, so I can download exactly the code of the chapter I'm reading.
  • Teaches you both: Annotations and XML configurations. You never know when you need to open those legacy XML files...
  • Chapter 7 (JSF and AJAX) and Chapter 8 (JSF and HTML5) are the ones I liked the most since these topics are a must in today's web applications.


For more information go to:
https://www.packtpub.com/application-development/mastering-javaserver-faces-22

See ya!

Thursday, December 18, 2014

USD $5 Bonanza from Pack Publishing is Back!

Just a quick post with a great offer from Packt Publishing:

From December 18th 2014 until January 6th 2014, you can get any eBook or Video from Packt for just USD $5!

More info: http://bit.ly/13fDngD

This is a great offer to start the new year (2014) with some books to read. Go get yours!




Friday, October 3, 2014

JavaOne 2014 - Tuesday

Hi all, here are my notes of the sessions I attended on Tuesday at JavaOne.

Where is my Memory
Important session about managing memory on your JVM. The speaker introduced us to the different memory regions on the JVM and gave us good advices about how to find memory leaks on your JVM.

Some of the tips we got during the session:

The less options you have at your startup script, the better!

if you want to know default options for your JVM use the following:
java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version

Of course you always want to go with non-default sizes, but you should go with small increments of memory for your -Xmx and -XX:MaxPermSize options

An Important difference between Java 8 and prior versions of Java is that Java 8 got almost all the naked memory available and if you want to tune it, then you should reduce it

Developers do not think about memory, they don't destroy objects or freed memory because of the Garbage Collector, which is a subsystem of the JVM for reclaiming "unused" memory

There are some objects that are always alive and wont be collected by the garbage collector, which are called GC Roots

  • System classes
  • JNI references
  • Running Threads
  • Local variables or parameters
  • Native stack
  • Used monitors
  • And some others

This is how the garbage collector works:

  • Mark all GC Root as reachable
  • Mark all objects referenced from reachable object as reachable too
  • Repeat until all reachable objects are found
  • Everything else is garbage 

So, what is a Memory Leak?
Reachable objects that will never be used by your application and/or the repetitive creation of such objects. Some examples of memory leaks are:

  • Caches without look-ups and eviction
  • String.substring -> Prior to Java SE 7
  • Immortal threads
  • Unclosed IO streams

The symptoms of your memory leak are either OutOfMemoryError or the application runs too slow due to the excessive GC, but be careful since there may be false positives due to:

  • Too high allocation size 
  • Cache with the wrong size - Check the size of your cache
  • Trying to load too much data at onces - You can use lazy loading
  • Fat data structures - Inneficient datastructures to hold your data

Memory monitoring tools

  • VisualVM/Java Mission Control
  • jStat
  • GC logs - Use the following options -XX:+PrintGCDetails -XX:PrintGCTimeStamps -Xloggc:file.log -XX:+UseGCLogFileRotation -XX:Number at your startup script and then use GC log analyzers such as Fasterj or GCViewer

So you have a memory leak, then try this as first step

  • Reduce memory usage
  • Tune GC
  • Increase Xmx/PermGen

If it doesn't work, then you should try more advanced techniques such as Memory (Heap) dump to find out what consumes memory. Memory dump is a binary representation of objects graph written to a file. Have in mind that it is not an accurate representation of the memory but is good enough to find memory leaks.

In order to get a memory dump you can use one of the following:

  • jmap -dump:format=b,file=heap.hprof
  • Add this options to your startup script:
    -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./java_pid<pid>.hprof

The tool used to analyze the Memory Dump is Eclipse Memory Analyzer and you should look for objects with the biggest retained size.

A final word from the speaker:
Do not use Profilers to find Memory Leaks!

More information about solving Memory leak can be found at:
https://plumbr.eu/blog/solving-outofmemoryerror-story-of-a-developer


Hackergarten
Went to the Hackergarten again and during the time I was there I met Werner Keil one of the spec leads of JSR 363: Units of Measurement API, who walked me through the status of the JSR and point me to several documentation sources. This JSR is also available to adopt through the Adopt a JSR program.




RIA Technologies and Framework Panel
There was this excellent panel of experts in the RIA topic. They discussed about the state of art regarding to RIA technologies.

Native or HTML5 ?
There were a lot of opinions here, but at the end, most have agreed that in house development for administrative purposes should go HTML 5. But if you really need to get the best of the platform go native even if you have to do it for three different platforms. The audience were asked if we were doing native development for our mobile projects, just a few raised their hands.
An advice to promote code reuse is to develop your backend to return JSON so your native apps or HTML 5 apps con consume it.

Is JavaFX the future of client side Java?
Some have said Swing is gone, JavaFX is the present of client side Java, but, the audience were asked whether they were building desktop applications and many raised their hands. Then they were asked whether they were using JavaFx or Swing... and most of them are using Swing and are not planning to move to JavaFx... So the question remains and is not clear whether JavaFx is replacing or not Swing.

Last question was about what panelist are excited about for the next years?
Swing + HTML 5 - Andres Almiray
No Wrappers for HTML 5 apps - Max Katz
iOS SwiftKevin Nilson
Curious about what will happen on the UI market - Gerrit Grunwald
What new tools will come up for UI - Sven Reimers


Delivering Oracle ADF Projects: Modern Techniques
This session was really interesting because it was about using modern development techniques on the world of ADF. We saw how we can use plugins for quality of code in ADF. Also explored how testing ADF applications can be automatized by using the Oracle Application Testing Suite. Last but not least, we saw how we can use Maven with ADF. I am excited about this new feature since I've wanted to create a continuous integration environment with ADF for a while. I think I found what my next talk about ADF is going to be...


ODTUG Oracle Developers Meetup
Had the chance to meet ADF celebrities and other ADF developers on the Oracle Developers meetup, an event organized by ODTUG. I could see how popular ADF is becoming, more developers are now working with this technology and are excited about the new releases.




Oracle ADF Enterprise Architects Birds­of­a­Feather Meeting
This session was about architectural challenges that we face when developing with ADF. The session was more Q&A oriented. Some of the participants were Sten Vesterli, Chris Muir and Frank Nimphius. So imagine you, with some ADF questions and having these ADF masters in front of you to help you find your path... that's priceless.


At night we went to the Red Hat party, where we could hangout with Arun Gupta, Kevin Nilson and Dario Laverde. Had some drinks and food and enjoyed the end of day 3 at JavaOne! What a great day.





see ya!