JDeveloper: access resources from the applications jar or classpath in the Model or ViewController

This bog describes how to read resources, which are part of the applications classpath and are deployed with the application.

Use Case
You want to read a resource e.g. a property file in the model layer or the view layer or an image which is part of the deployed application. As you don’t know where exactly the application is deployed, you can’t use the normal java.io.* classes as they require an absolute path to the file to read.

Implementation
In the Sample which is provided with this blog (see the link at the end of the blog) we read a properties file ‘model.properties’ in the model layer and make the values abailable via a service method in the application module. In the view layer we similar read another properties file ‘view.properties’ which we access through a bean method.

The UI consists of only one page which has two panelForms. Each has an inputText component where you can enter the key of the property you want to read, a button to activate a method to read the property and an outputText to show the result.

Running application

Running application

Model project resources:

# Model resources
ModuleName=BARTPAppModule
CreationDate=2012-08-01
EmptyKey=

ViewController project resources:

## Properties file for hte view controller
ViewControllerName=Hallo ik bin ein Berliner
CreateDate=2012-08-02

After entering a key value we get the values displayed:

Running application after getting some values

Running application after getting some values

Let’s start with the implementation in the model layer. In the application module implementation class we add a service method which is implemented as singleton (for the module), meaning that the resource is only loaded once and stored in the application module. Activation and passivation don’t need to be handled here, as the resource is read again after each activation as the local variable mModelProperties will be null after an activation.

public class BARFPAppModuleImpl extends ApplicationModuleImpl implements BARFPAppModule {
    private static ADFLogger _logger = ADFLogger.createADFLogger(BARFPAppModuleImpl.class);
    private static String PROPERTY_FILE = "de/hahn/blog/accessresourcesfrompath/model/resources/model.properties";
    Properties mModelProperties = null;

    /**
     * Returns the value of a property read from the model property file
     * @param key of the property to retrieve
     * @return value of the key or null if not found
     */
    public String getModelResource(String key) {
        // read property file only once
        if (mModelProperties == null) {
            initProperties();
        }

        return mModelProperties.getProperty(key);
    }

    /**
     * load the properties from the resource file
     */
    private void initProperties() {
        InputStream asStream = this.getClass().getClassLoader().getResourceAsStream(PROPERTY_FILE);
        if (asStream == null) {
            _logger.severe("Could not load property file: '" + PROPERTY_FILE + "'");
            mModelProperties = new Properties();
            return;
        }

        mModelProperties = new Properties();
        try {
            mModelProperties.load(asStream);
        } catch (IOException e) {
            e.printStackTrace();
            _logger.warning("Can't load properties: " + e.getMessage());
        }
        _logger.info("Model properties loaded!");
    }
...
}

The essential part is to use the class loader to read the resource as stream (line 24). The class loader allows us to read resources from the class path itself without knowing the absolute path in the file system. You only need to know the package structure and replace the ‘.’ which delimit the packages with the ‘/’. The class loader can then access all folders relative from its own load point. For more information check ClassLoader java doc.
The rest of the implementation is easy now. The same technique is used in the bean of the view controller project. Here we implement the method in a bean which we call on the click of a button ‘getViewReource’.

public class ResourceReaderBean {
    private static ADFLogger _logger =
        ADFLogger.createADFLogger(ResourceReaderBean.class);
    private Properties mViewProperties = null;
    private static String PROPERTY_FILE =
        "de/hahn/blog/accessresourcesfrompath/view/resource/view.properties";

    private void initProperties() {
        // instead of using the de.hahn.testproxy.backingbeans.test.properties you have to use de/hahn/testproxy/backingbeans/test.properties
        InputStream asStream =
            this.getClass().getClassLoader().getResourceAsStream(PROPERTY_FILE);
        if (asStream == null) {
            // file not found
            _logger.info("File not found: '" + PROPERTY_FILE + "'");
            return;
        }
        mViewProperties = new Properties();
        try {
            mViewProperties.load(asStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (!mViewProperties.isEmpty()) {
            _logger.info("Properties loaded: " + mViewProperties.toString());
        }

    }

    public void getViewResourceListner(ActionEvent actionEvent) {
        String value = "";
        // read property file only once
        if (mViewProperties == null)
            initProperties();

        BindingContainer bindingContainer =
            BindingContext.getCurrent().getCurrentBindingsEntry();
        AttributeBinding attrKey =
            (AttributeBinding)bindingContainer.getControlBinding("ViewResourceKey1");
        String key = (String)attrKey.getInputValue();
        if (mViewProperties != null && key != null) {
            String val = mViewProperties.getProperty(key);
            AttributeBinding attrValue =
                (AttributeBinding)bindingContainer.getControlBinding("ViewResourceValue1");
            attrValue.setInputValue(val);
        }
    }
...
}

The key to load from the resource is read from the binding variable ‘ViewResourceKey1’, the returned value is put back into the binding variable ‘ViewResourceValue1’. Both are defined in the variables section of the pageDef of the ShowProperty.jspx page.

You can download the sample from here BlogAccessResourcesFromPath.zip.
The sample was built with JDev 11.1.1.6.0 and uses the HR schema.

Advertisements

JDeveloper: Way to show a Version Number in the UI

My last presentation at the German ADF Partner Community showed how to put a version number into an application ear and allows two versions of the same application to exist on a managed WebLogic Server. One question I got from the audience was how to show this version in the UI of the application. This blog post shows one way of doing this.
For those readers which do not know how to put a version number into an application EAR before deploying it to a WLS, lets start with this.
Andrejus Baranovskis has a blog post How to set EAR Version for ADF Application on WebLogic about this which uses a more hand coded approach. Edwin Biemond showed a small ant script to do is. I will show you a different solution using ANT.
This solution consists of a general GeneralVersionBuild.xml ANT script and a project dependent VersoinBild.xml ANT script which sets some properties (the version properties) for the GeneralVersionBuild.xml. The GeneralVersionBuild.xml defines the targets to alter the different version numbers you define for your applications and print out the version in the log like

Versioninfo:
     [echo] VERSION: V1.0.0.3 DB.V1 vom 2012/02/12 21:09
     [echo] Major: 1
     [echo] Minor: 0
     [echo] Fix: 0
     [echo] Build: 3
     [echo] Date: 2012/02/12 21:09
     [echo] DB-Schema Version: 1
     [echo] --------------------------------------------------------------------------------------------------

The information above is the complied from the version.properties file which defines the different parts of the version number:

#Build version info
#Sun Feb 12 16:06:18 CET 2012
DBSchema=1
majorVersion=1
fixVersion=0
minorVersion=1
buildDate=2012/02/12 16:06
buildNum=39

To manipulate the properties we use the targets defined in the GeneralVersionBuild.xml ANT script. This is called by the project dependent VersionBuild.xml ANT script:

<?xml version="1.0" encoding="UTF-8" ?>
<project name="AVIVersionBuild" default="make" basedir=".">
    <!-- # Relativ path to the base of the application -->
    <property name="root.dir" value=".."/>
    <property name="earFileBaseName" value="BlogAccessVersionInfo"/>
    <!-- PATH TO VERSION.PROPERTIES FILE (e.g.: src/de/hahn/blogxxxx/view/version.properties) -->
    <property name="file.version.properties" value="src/de/hahn/blog/accessversioninfo/view/version.properties"/>
    <property file="${file.version.properties}"/>
    <property name="deployFolder" value="../deploy/"/>
    <!-- PATH TO THE GENERAL VERSION BUILD ANT SCRIPT -->
    <import file="${root.dir}/Versionierung/GeneralVersionbuild.xml"/>
</project>

All we need to do is to set the Versionbuild.xml file as ANT”Project Buildfile” file

Setup Ant Project Buildfile

Setup Ant Project Buildfile

Now that the project has a version.properties file (at src/de/hahn/blog/accessversioninfo/view/version.properties) holding information about the current version of the application we need a way to access this information on a page in the UI. As we are using a property file we can bind this file as resource bundle into the project and access the parts (properties) with EL.
To add the version.properties file as resource bundle we open the project properties, select the “Resource Bundle” node and then set the properties from the bundle as outputText onto the page.

Make sure that you select the right project when you add a property file.

Add a property file as bundle

Add a property file as bundle


Next search for the version.properties file in the project
Select version.properties

Select version.properties


Now in the page we can access the property via EL. We drag an outputText component on the page and select its value from Resource bundle
Select a value from resource bundle

Select a value from resource bundle


Select value from property file

Select value from property file


This will create this entry in your page

<c:set var="aviviewcontrollerBundle"
   value="#{adfBundle['de.hahn.blog.accessversioninfo.view.version']}"/>

and here is the resulting outputText:

<af:outputText value="Version: #{aviviewcontrollerBundle.majorVersion}.#{aviviewcontrollerBundle.minorVersion}.#{aviviewcontrollerBundle.fixVersion}.#{aviviewcontrollerBundle.buildNum} from #{aviviewcontrollerBundle.buildDate}" id="ot6"/>

and the resulting page when you run the application

Running application

Running application

As you see the name of the resource bundle is set to “aviviewcontrollerBundle” (the default bundle name). This happens if you don”t already have a default bundle defined which contains a key value pair. You can rename it to e.g. “versioninfo” to make clear what the bundle is used for. In this case you have to change the EL to access to properties too.

    <c:set var="versioninfo"
 value="#{adfBundle['de.hahn.blog.accessversioninfo.view.version']}"/>
...
 <af:panelGroupLayout id="pgl2">
    <af:outputText value="Version: #{versioninfo.majorVersion}.#{versioninfo.minorVersion}.#{versioninfo.fixVersion}.#{versioninfo.buildNum} from #{versioninfo.buildDate}" id="ot6"/>
 </af:panelGroupLayout>
...

The sample workspace can be downloaded from here BlogAccessVersionInfo.zip. Please rename the file to ‘.zip’ after downloading it! It was build using JDeveloper 11.1.2.1 and uses the HR schema.