During our Oracle MAF Hackathon we wanted to deploy our app to both android emulator and iOS simulator. Feeling giddy because of having XCode5 and Android SDK installed on my Mac I wanted to show our crowd that apps built with MAF are really multi-platform compliant. Confident of victory because deployment to android emulator succeeded a few weeks ago I started deployment. But this time an INSTALL_FAILED_CONTAINER_ERROR exception occurred:

After copying the “command-line executed” from log messages window into console a more detailed error message was shown.

Actually this error message does not point out the issue’s cause. In our case deployment failed because I upgraded my Mac OS X from Maverick to Yosemite what entailed the Intel Hardware Accelerated Execution Manager (HAXM) did not longer work. The emulator’s android virtual device (AVD) I used for deployment was configured to run with hardware accelerated „Intel Atom (x86)“ CPU instead of ARM. Switching this back to „ARM“ solved the problem with the side-effect of losing hardware accelaration. Recognizing that something with HAXM went wrong I decided to upgrade my HAXM installation via Android SDK Manager. HAXM can be found under node „extras“:

After upgrading my HAXM installation there were two dmg packages: One for Mac OS installations below 10.9 and one for Mac OS X 10.9 and above.

Re-installing the appropiate package for Maverick/Yosemite (10.9 or higher) re-enabled me to deploy our Oracle MAF app to an android emulator’s AVD that uses an Intel CPU with hardware acceleration.

Maybe this helps someone out there to save time for investigating the cause of the error message we got during deployment.

[...]Caused by:java.lang.UnsupportedOperationException:setXIncludeAware is not supported

on this JAXP implementation or earlier:class oracle.xml.jaxp.JXDocumentBuilderFactory

at javax.xml.parsers.DocumentBuilderFactory.setXIncludeAware(DocumentBuilderFactory.java:614)

To resolve this issue you can configure your ADF12c application to use a specific implementation of DocumentBuilderFactory. This is quite simple and straightforward. Just configure your weblogic specific deployment descriptor (weblogic-application.xml) to use

1

com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl

as application’s DocumentBuilderFactory implementation. This is what worked for us. Other implementations of DocumentBuilderFactory might be valid, too. To configure the DocumentBuilderFactory you can use JDeveloper tooling:

This will put the following lines into your weblogic-application.xml:

1

2

3

4

5

6

7

<xml>

<parser-factory>

<document-builder-factory>

com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl

</document-builder-factory>

</parser-factory>

</xml>

To dodge possible other unsupported operations, we also provided values for SAX Parser Factory and Transformer Factory:

Prerequisites

Follow ups

Without providing any configuration file log4j2 will log our messages on console. To configure another behavior just put a configuration file into your project’s src directory (e.g. ./Model/src or ./ViewController/src). The configuration file itself can be written in XML, JSON, or YAML. For more information on the expected syntax have a look at log4j2’s official documentation.

Problem

In one of our Oracle APEX 4.2 projects we wanted to use the famous jQuery UI autocomplete feature. By default, APEX 4q.2 applications contain a subset of jQuery UI (see Oracle APEX 4.2 Documentation for more details). It is a pity autocomplete functionality is not part of that subset. Fortunately, the APEX server is shipped with the necessary libraries. That makes it easy to include them. When looking at the file structure of our APEX server, you can see that there are multiple versions of jQuery UI.

Each of these version folders contains a corresponding version of the autocomplete feature.

So, what is the correct version to include?

Using a JavaScript console it is quiet easy to determine the jQuery UI version which is automatically included by APEX. Just type

1

jQuery.ui.version

into your console’s CLI and have a look at the output.

Recognizing our jQuery UI version is 1.8.22 one way to include the appropriate version of our jQuery UI autocomplete feature would be to insert the following code into our page header.

But there is one serious disadvantage using this pragmatic approach. When you upgrade your APEX server in the future your APEX application might break. Why? Because the core jQuery UI libraries published by the APEX server could have another version. So our manually loaded autocomplete feature might not be compatible with this newer autoloaded jQuery UI version.

But don’t panic, there are solutions to keep the libraries in sync. I will explain three possible solutions using the following simple sample page. It contains a region called “jQuery AutoComplete Region” with one page item “P2_AUTOCOMPLETE_ITEM”.

When running the page without the autocomplete feature we are able to type some text into P2_AUTOCOMPLETE_ITEM. The input field works as designed, but this beavior is not so much impressive.

What we want to achieve is that P2_AUTOCOMPLETE_ITEM provides a list of suggestions using jQuery UIs autocomplete feature.

Solution 1 – Extend jQuery UI version included by default

This solution is simple but powerful. Whereas jQuery and a subset of jQuery UI is loaded by default, our task is to manually load the corresponding version of jQuery UI’s autocomplete module.The only thing we have to do is to put the following Immediately-Invoked Function Expression (IIFE) into the page header

If the currently loaded jQuery object does not contain jQuery UI’s autocomplete module we will manually load it into the page. For that reason we build the URI of our jQuery UI autocomplete javascript file which is related to the currently loaded jQuery UI version (line 26). Please notice that we want to load the minified version of the file. The script itself is loaded using jQuery’s getScript() function (line 30). After jQuery UI autocomplete has been included we are able to bind the list of suggestions (line 4 pp.) to our input text field (line 18). To ensure the binding is invoked after the script has been loaded it is called by jQuery’s when()-function (line 30).

In order to test our code, we run our sample page once again. When typing the letter “j” into our input text field the expected autocomplete box appears!

Choosing this approach we ensure, that the versions of the autoloaded jQuery UI components and the manually loaded extension are in sync. This is upgrade-safe, as long as the jQuery UI API is not changed in future versions. If this is acceptable to you, solution 1 should be your choice.

Solution 2 – Include and use older jQuery/jQuery UI version

When implementing custom jQuery/jQuery UI based functionality in your APEX application, you are sure that the code works with the jQuery/jQuery UI versions you used to implement your code. As written in the introduction of this article the APEX server is shipped with multiple versions of jQuery. So, if the libraries we used to implement our custom behavior are delivered with future versions of APEX, it would be smart to use them.

When implementing custom jQuery based code, we have to determine the currently used jQuery-Version. Type

1

$.fn.jquery

into your JavaScript console’s CLI and take the output. Let’s assume the output says your jQuery version is 1.7.1.

Keeping this information in mind, we have to edit the page template. Within the page template we can include jQuery 1.7.1 combined with jQueryUI 1.8.22 and assign it to a JavaScript variable jQuery1_7_1_UI1_8_22. In order to achieve this, we have to edit our page template. To open the edit view just double-click on the page template link in the application builder’s page view:

Insert the following code just before the #APEX_JAVASCRIPT# substitution string that appears in the “header” section. In APEX versions prior to 4.2 insert code before #HEAD# substitution string.

This ensures, that jQuery version 1.7.1 is loaded (line 1). This jQuery version is extended by jQuery UI 1.8.22 (line 2), which itself is extended by jQuery UI autocomplete feature 1.8.22 (line 3). The whole setup is stored into JavaScript variable jQuery1_7_1_UI1_8_22 (line 6).

In order to use jQuery 1.7.1 instead of the APEX default jQuery version, we have to change the arguments (last line) of our Immediately-Invoked Function Expression (IIFE) in our page header from

1

})(jQuery,window,document);

to

1

})(jQuery1_7_1_UI1_8_22,window,document);

As a result code within the IIFE will use jQuery 1.7.1 instead of the jQuery version shipped with the APEX server. The rest of your APEX application will use the version shipped with APEX. The benefit you get using this solution is, that your code always runs against the jQuery version you used to develop the code. The disadvantage is that you have to trust in Oracle that future versions of APEX will be delivered with “your” jQuery/jQuery UI version.

Solution 3 – The best of 1 and 2

To avoid the disadvantages of solutions 1 and 2 it would be nice if the jQuery/jQuery UI versions you have used during development would only be used if they are available.

No problem!

Just perform all steps of solutions 1 and 2, but change the arguments of the IIFE call from

This ensures that “your” jQuery-Version (1.7.1) is only passed into IIFE, if it has been loaded and extended by “your” jQuery UI version 1.8.22. Otherwise the default jQuery version delivered by APEX server will be used.

In one of our famous APEX projects we had the requirement to select a month from a select list. The select list itself should contain all months half a year before and half a year after current date. Below you can see the select-statement of our LOV. Maybe it will be helpful for somebody out there.

As you can see in the signature of the second addTab-method, UI Shell provides the possibility to pass a Map<String, Object> that holds parameters for our task flow. Keeping that knowledge in mind we are able to modify the Launcher class provided by OTN in two steps:

1. Overload method _launchActivity

In order to overload the pre-implemented _launchActivity method edit Launcher.java and insert the following code snippet:

2. Simplify old _launchActivity method

For consistency reasons we should modify the “original” _launchActivity method in the following way:

1

2

3

4

privatevoid_launchActivity(Stringtitle,StringtaskflowId,

booleannewTab){

this._launchActivity(title,taskflowId,newTab,null);

}

An example of passing a parameter into a taskflow is shown below. Create a button within your navigation area. Define the following code snippet as an action listener method of that button (insert code into your launcher class).

1

2

3

4

5

6

7

8

publicvoidlaunchWithParameterTaskFlow(ActionEvent actionEvent){

Map map=newHashMap();

map.put("inParameter","Hello World!");

_launchActivity("ParameterTaskFlow",

"/WEB-INF/flows/parameterTaskFlow.xml#parameterTaskFlow",

false,map);

}

So, what does this new method cause? When the button is clicked we generate a HashMap that contains the parameter inParameter with its value “Hello World!”. This map is used to pass the containing parameter into the taskflow via _launchActivity method.

Sample Taskflow

This paragraph describes how to build a sample taskflow. The taskflow itself contains a single view activity with a corresponding page fragment. To use the inParameter we want to pass, we have to define an input paramter in our taskflow. To do this open the taskflow and click somewhere, but not onto the view activity. The property inspector should show the task flow definition attributes now. Under section Parameters we can see the subsection Input Parameter Definitions. Click the green plus to add a new parameter. Name the parameter inParameter and define that its class is java.lang.String. The fields “value” and “required” should be empty. Have a look at the image below to see an overview of the desribed information in this paragraph. As you can see, the name of the task flow input parameter must match the key we passed in our parameters map via _launchActivity method.

As intended, we are able to use the input parameter within the taskflow by using the EL expression #{pageFlowScope.inParameter}.

Yesterday I installed Linux Mint Debian Edition (LMDE) on my notebook. It seems to be a rock solid distribution, but as Clem announced in his blog post it has “some rough edges”. One rough edge I had been experiencing was an annoying “no space left on device” error when I tried to install Oracle JDeveloper on my brand new system. Believe it or not: The error cause is not a bug – it is a feature! This post is about fixing the installation issue caused by that feature. Although it talks about a JDeveloper installation the suggested ways can be a applied to other programs that cause the issue mentioned above.

Scenario

As described in the previous paragraph I tried to install Oracle JDeveloper 11.1.1.6.0 on my notebook:

1

java-jar jdevstudio11116install.jar

After a few seconds the following window was popping up:

Cause Analysis

The error description “no space left on device” was a little bit confusing to me, because I just installed LMDE on a 500 GiB hard disk and I could not imagine that LMDE would have occupied the whole disk space. When checking the free disk space with

1

df-k

I recognized the high usage of the /tmp partition (96%, line 6):

1

2

3

4

5

6

7

Filesystem1K-blocks UsedAvailableUse%Mounted on

rootfs477387180157140564377781364%/

udev4032380040323800%/dev

tmpfs8075569128066441%/var/run

tmpfs5120051200%/var/run/lock

tmpfs161511215411247398896%/tmp

tmpfs16151127616150361%/var/run/shm

Newer debian (linux) systems allow to use RAM as a “directory” for writing / reading temporary data. This increases speed of programs that need space for temporary data. For the most use cases the size of such a RAM-based temporary partition is adequate. An insurgent program that needs a huge amount of temporary space is the Oracle JDeveloper installer. It looks up the system’s temp directory in order to extract round about 2 GiB of data to that directory. So the cause of the occuring “no space left on device” error was the huge amount of data the installer tried to write to my limited RAM-based /tmp partition.

Solutions

There are (at least) three ways to solve the issue.

Solution 1 – Dynamically resize /tmp at runtime

Because /tmp is mounted as a tmpfs you can resize it dynamically at runtime. Just clear the content of /tmp and resize its space:

1

2

3

sudo rm-rf/tmp/*

sudo mount-oremount,size=2560m/tmp

java-jar jdevstudio11116install.jar

This is the recommended way, because it ensures a fast running installation process. For installing JDeveloper the size of 2560m (= 2.5 GiB) was adequate. Depending on your use case you might have to choose a higher value like 3g (= 3 GiB).

Another solution is to prevent /tmp from being mounted as RAM based tmpfs. To achieve this perform the following two simple steps and you are done:

Edit /etc/default/rcS as superuser and replace RAMTMP=yes by RAMTMP=no

reboot

Works like solution 2, but is not java specific. In contrast to the first two solutions, it has a permanent effect. You should choose this option, if you are constantly experiencing the “no space left on device” error when running various programs.

Please note: A filled to overflowing /tmp partition is not the only matter that can cause a no “space left on device” error. If you are not able to identify a chock-full /tmp partition by using

1

df-k

try

1

df-i

to see, if you are running out of inodes. If you are able to identify a value near 100% follow the instructions on Ivan Kuznetsov’s blog.

In one of our APEX 4.x projects I had to refresh an iframe (id=”P123_IR_IFRAME”) dynamically at runtime. An easy to use and similarly pragmatic way is to reassign the iframe’s source attribute via jQuery:

1

2

3

4

$('#P123_IR_IFRAME').attr(

"src",

$('#P123_IR_IFRAME').attr("src")

);

This approach has been tested with various versions of Firefox, Internet Explorer, Opera and Chrome.

Blog about Oracle ADF, MAF and related technologies

Suche nach:

Communities

About

Welcome to my blog! My name is Hendrik Gossens and I work as an IT Consultant at OPITZ CONSULTING, Germany. My focus is on Oracle technology, especially on Oracle ADF and Oracle MAF. This blog is a kind of private knowledge base containing information and howtos on Oracle ADF, MAF and related technolgies. Maybe those information are also interesting to someone out there. Human knowledge belongs to the world!