Friday Aug 30, 2013

Dealing with ADF_FACES-30214

Whilst doing some work on a separate blog entry using the demo Summit application in 12c I noticed a message repeated again and again in the WebLogic log in the console. Nothing annoys me more that constantly repeating messages that obscure the stuff I really want to see (I've wrapped the message to fit here) :

 <Warning> <oracle.adfinternal.view.faces.renderkit.rich.DocumentRenderer> 
   <ADF_FACES-30214> <The setting to enable version display will be ignored 
   because the application is running in production mode.>

Switching this message off is super easy, as we'll see, but what does it relate to?

Well, this is all to do with the following context parameter defined in your web.xml file

  <context-param>
    <description>Whether the 'Generated by...' comment at the bottom of ADF Faces HTML pages should contain version number information.</description>
    <param-name>oracle.adf.view.rich.versionString.HIDDEN</param-name>
    <param-value>false</param-value>
  </context-param>

This parameter defines if the generated page output contains detailed information about the ADF version. This information is useful in development and QA evironments but is not something that you want in a production environment as it is of potential use to a Hacker. So, to see the version information we need to explicitly include this context paramter and set the value to false so as not to hide the version info.

Now in JSF 2 we have an additional factor come into play to complicate matters, which is the Project Stage (there are several articles on Project Stage that you can find with your favorite search engine, but this one covers the basics). Basically Project Stage is a way that you can define an application as being in Development, Test or Production mode and effect changes accordingly (both in the declarative sense as we have an example of here, but also in terms of code and behaviors). 

Now the problem that all this relates to, the unwanted log message, is a reflection of the fact that if the Project Stage is not explicitly defined then it's going to default to Production mode (hopefully the message begins to make sense now?) . So we kind of have two mutually exclusive settings in this app.  On one hand I'm asking for Development time version information, and on the other hand the app thinks it's in production mode. The result is this message, and, if you look at the actual source of the page in the browser you'll see this:

<!--Created by Oracle ADF (Version information hidden), 
    accessibility (mode:null, contrast:standard, size:medium), 
    skin:skyros-v1.desktop (skyros)-->

The fix?  Well I do want to see the version information so I need to tell the application that it's in Development mode, not Production mode. To do this I just have to add a Project Stage entry into web.xml:

  <context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>    
    <param-value>Development</param-value>
  </context-param> 

(Note the value is capitalized "Development")  

Now when the application is re-deployed, the pesky message has gone and the page source contains oodles of version information:

<!--Created by Oracle ADF (ADF RichClient API - ABRAMS (custom: 12.1.2.0.40.66.68) 
  / ADF RichClient Impl - ABRAMS (custom: 12.1.2.0.40.66.68) 
  / ADF-Controller{Oracle-BuildSystem=Linux - java - 1.7.0_10-b18, 
  Oracle-Label-JDEVADF=JDEVADF_12.1.2.0.0_GENERIC_130608.2330.6668, 
  Oracle-Version=12.1.2.0.40.66.68, Created-By=23.6-b04 (Oracle Corporation), 
  Oracle-Builder=Official Builder, Oracle-Label=JDEVADF_12.1.2.0.0_GENERIC_130608.2330.6668, 
  Oracle-BuildTimestamp=2013-06-09 02:39:02 -0700} 
  ADF-Model{Oracle-BuildSystem=Linux - java - 1.7.0_10-b18, 
  Oracle-Label-JDEVADF=JDEVADF_12.1.2.0.0_GENERIC_130608.2330.6668, 
  Oracle-Version=12.1.2.0.40.66.68, Created-By=23.6-b04 (Oracle Corporation), 
  Oracle-Builder=Official Builder, Oracle-Label=JDEVADF_12.1.2.0.0_GENERIC_130608.2330.6668, 
  Oracle-BuildTimestamp=2013-06-09 01:58:04 -0700} 
  ADF-Share{Oracle-BuildSystem=Linux - java - 1.7.0_10-b18, 
  Oracle-Label-JDEVADF=JDEVADF_12.1.2.0.0_GENERIC_130608.2330.6668, 
  Oracle-Version=12.1.2.0.40.66.68, Created-By=23.6-b04 (Oracle Corporation), 
  Oracle-Builder=Official Builder, Oracle-Label=JDEVADF_12.1.2.0.0_GENERIC_130608.2330.6668, 
  Oracle-BuildTimestamp=2013-06-09 12:47:43 -0700}  / powered by JavaServer Faces - 1.0.0.0_2-1-20), 
  accessibility (mode:null, contrast:standard, size:medium), skin:skyros-v1.desktop (skyros)--> 

Next time I show how you can use a WebLogic Deployment Plan to update the Project Stage as you deploy your application 

Tuesday Jul 30, 2013

(Adventures in) ADF Logging in 12c

An offline conversation with Andrejus Baranovskis the other day alerted me to a difference in behavior with the ADF Logger in 12.1.2. It seems that the logging output is not being output to the console as it was in 11g, although it's certainly being written to the log file OK.

I did a little testing and digging on this, and the issue it turns out is pretty simple.

The root cause is in the default definition of the console hander in the logging.xml file. In 11g, this handler is configured to let everything through level="ALL".  In 12c the default configuration is only to pass more significant issues through to the console level="WARNING:32".  The reason for this change is, I'm guessing to reduce the amount of general noise that you see when WebLogic is started. 

So it's trivial to switch back to the verboseness of 11g if you'd like to:

  1. From the console choose Actions --> Configure Oracle Diagnostic Logging to open the logging.xml view
  2. Switch to source view and locate the <log_handler name='console-handler' ... entry
  3. Change the WARNING:32 value to ALL

If you are feeling more creative, and want the best of both worlds, you can of course define a second handler for the console with this more permissive value and assign that explicitly to just your loggers - then you can get the verbose output for your logging without everything else.  

For example;

1. Define a custom handler 

<log_handler name='demo-console-handler' 
             class='oracle.core.ojdl.logging.ConsoleHandler' 
             formatter='oracle.core.ojdl.weblogic.ConsoleFormatter'
             level="ALL"/> 

2. Use the custom handler for your root logger:

<logger name="oracle.demo" level="FINEST" useParentHandlers='false'>
  <handler name='odl-handler'/>
  <handler name='wls-domain'/>
  <handler name='demo-console-handler'/>  
</logger> 

Monday Jul 22, 2013

Setting up a standalone WebLogic 12c install for ADF Without a Database

One change that many folks have encountered with the 12c (12.1.2) release of WebLogic and ADF concerns the setup of stand-alone WebLogic instances extended with JRF for ADF Application deployment. 

The main problem comes when creating the JRF extended domain.  On page 6 of the config process screen you are confronted by the following:

Configure Database Screen

Note here that you need to provide information for the database that OPSS should use. 

Now this connection has a real purpose, the Oracle Platform security infrastructure for 12c needs to store it's information within a proper database so as to correctly (and supportably) manage itself across multiple servers in a cluster.  However, if like me, you just wanted to stand up a single unclustered ADF enabled WebLogic for testing deployments etc. This could be a bit of a pain, particularly in my case as the database version I'm currently running is not of the correct version.  So here I'm documenting the steps for avoiding this requirement on a single standalone server, although I stress, as far as I am aware, this is not a supported configuration for production usage.

The Steps to Install Without Needing a Database 

  1. First of all install WebLogic (wls_121200.jar) and the ADF runtime (fmw_infra_121200.jar) into the same 12c Oracle Home using their respective installers. At the end of each of the WebLogic install make sure you uncheck the Configuration Wizard launch option as we'll be doing that manually later. 
  2. Start a shell / command prompt in $MW_HOME/wlserver/common/bin
  3. Set the environment variable QS_TEMPLATES to point to $MW_HOME/wlserver/common/templates/wls/wls_jrf.jar
  4. Run qs_config.sh and define the name of the domain that you want to create (e.g. add_domain) along with the usual WebLogic passwords and ports that you require. Finish the Quick Start wizard without starting the new domain. 
  5. Now run the conventional config.sh and on the first page choose "Update an Existing Domain" rather than "Create a new domain". The new domain (e.g. adf_domain) should now be listed for selection.
  6. On the second screen choose the templates that you wish to apply, e.g. Oracle JRF, Oracle Enterprise Manager etc.  and move on through the wizard. 
  7. On the Database Configuration Type screen this time you will see an extra option where Embedded Database (JavaDB) is offered and pre-selected. Select that and continue with the domain setup as usual with whatever managed servers you need.

Again to re-iterate this is only a setup that I would recommend for a development / testing environment and of course you should not take this approach if you're setting up any kind of clustered environment, even for testing, as the shared database has a real purpose in that case. Also consider that if your application uses MDS then you'll most likely need an database repository anyway, so again, in that instance don't use this technique.  

The fact that the normal install for the ADF Web Runtime does not offer this non-database option should be taken a a strong hint as to how supported you will be running with this configuration in a production environment.  Don't ask me for certification or support guidance, please contact Oracle Support for that information.  

Further Reading

The use of an external RDBMS Security Store for WebLogic (the configuration that  this article bypasses) is discussed in the WebLogic Documentation:

Read that chapter for a better understanding of why the default JRF install asks you to define a database connection for this purpose and why I talk about only using the technique that I've outlined here for development purposes. 

Wednesday Jun 26, 2013

Adaptive Connections For ADFBC

Some time ago I wrote an article on Adaptive Bindings showing how the pageDef for a an ADF UI does not have to be wedded to a fixed data control or collection / View Object. This article has proved pretty popular, so as a follow up I wanted to cover another "Adaptive" feature of your ADF applications, the ability to make multiple different connections from an Application Module, at runtime.
Now, I'm sure you'll be aware that if you define your application to use a data-source rather than a hard-coded JDBC connection string, then you have the ability to change the target of that data-source after deployment to point to a different database. So that's great, but the reality of that is that this single connection is effectively fixed within the application right?  Well no, this it turns out is a common misconception.

To be clear, yes a single instance of an ADF Application Module is associated with a single connection but there is nothing to stop you from creating multiple instances of the same Application Module within the application, all pointing at different connections.  If fact this has been possible for a long time using a custom extension point with code that which extends oracle.jbo.http.HttpSessionCookieFactory. This approach, however, involves writing code and no-one likes to write any more code than they need to, so, is there an easier way? Yes indeed.  It is in fact  a little publicized feature that's available in all versions of 11g, the ELEnvInfoProvider.

What Does it Do? 

The ELEnvInfoProvider  is  a pre-existing class (the full path is  oracle.jbo.client.ELEnvInfoProvider) which you can plug into your ApplicationModule configuration using the jbo.envinfoprovider property. Visuallty you can set this in the editor, or you can also set it directly in the bc4j.xcfg (see below for an example) .
Configuration Editor
Once you have plugged in this envinfoprovider, here's the fun bit, rather than defining the hard-coded name of a datasource instead you can plug in a EL expression for the connection to use.  So what's the benefit of that? Well it allows you to defer the selection of a connection until the point in time that you instantiate the AM.
To define the expression itself you'll need to do a couple of things:
  1. First of all you'll need a managed bean of some sort – e.g. a sessionScoped bean defined in your ViewController project. This will need a getter method that returns the name of the connection. Now this connection itself needs to be defined in your Application Server, and can be managed through Enterprise Manager, WLST or through MBeans. (You may need to read the documentation [http://docs.oracle.com/cd/E28280_01/web.1111/b31974/deployment_topics.htm#CHDJGBDD] here on how to configure connections at runtime if you're not familiar with this) 
  2.  The EL expression (e.g. ${connectionManager.connection} is then defined in the configuration by editing the bc4j.xcfg file (there is a hyperlink directly to this file on the configuration editing screen in the Application Module editor). You simply replace the hardcoded JDBCName value with the expression.  So your cfg file would end up looking something like this (notice the reference to the ELEnvInfoProvider that I talked about earlier)
<BC4JConfig version="11.1" xmlns="http://xmlns.oracle.com/bc4j/configuration">
  <AppModuleConfigBag ApplicationName="oracle.demo.model.TargetAppModule">
    <AppModuleConfig DeployPlatform="LOCAL" 
                     JDBCName="${connectionManager.connection}" 
                     jbo.project="oracle.demo.model.Model" 
                     name="TargetAppModuleLocal"
                     ApplicationName="oracle.demo.model.TargetAppModule">
      <AM-Pooling jbo.doconnectionpooling="true"/>
      <Database jbo.locking.mode="optimistic">
      <Security AppModuleJndiName="oracle.demo.model.TargetAppModule"/>
      <Custom jbo.envinfoprovider="oracle.jbo.client.ELEnvInfoProvider"/>
    </AppModuleConfig>
  </AppModuleConfigBag>
</BC4JConfig>

Still Don't Quite Get It?

So far you might be thinking, well that's fine but what difference does it make if the connection is resolved "just in time" rather than up front and changed as required through Enterprise Manager?
Well a trivial example would be where you have a single application deployed to your application server, but for different users you want to connect to different databases. Because, the evaluation of the connection is deferred until you first reference the AM you have a decision point that can take the user identity into account.

However, think about it for a second.  Under what circumstances does a new AM get instantiated? Well at the first reference of the AM within the application yes, but also whenever a Task Flow is entered -  if the data control scope for the Task Flow is ISOLATED.  So the reality is, that on a single screen you can embed multiple Task Flows, all of which are pointing at different database connections concurrently.

Hopefully you'll find this feature useful, let me know... 


Tuesday Jun 11, 2013

Prioritizing your messages

I've just uploaded a small sample onto the ADF EMG Samples site which demonstrates how you can make the <af:messages> component behave differently based on the messages that are in the queue.  The use case here was within a system where we wanted to use in-line messages for those run-of-th-mill type messages that should not really interrupt the flow of the user's activity (informational messages such as "Record Saved") , however, if something goes wrong then we wanted a popup to get in the users face, so to speak. 

The mode of display within the messages tag is controlled by the inline property, so in the sample application, rather than hardcoding this instead I evaluate an EL expression that returns a boolean.  Here's the code that implements the method I call:

public boolean isInlineMessage(){
  boolean lowPriorityMessage = true;
  Iterator<FacesMessage> iter = FacesContext.getCurrentInstance().getMessages();
  while (iter.hasNext()){
    FacesMessage msg = iter.next();
    if (msg.getSeverity() == FacesMessage.SEVERITY_ERROR || 
        msg.getSeverity() == FacesMessage.SEVERITY_FATAL){
      lowPriorityMessage = false;
      break;
    }
  }
  return lowPriorityMessage;
}

In this code I simple iterate through the message stack and check to see if there are any messages at the ERROR or FATAL level. If that is the case I return false rather than true for the method result.

The only twist here is to ensure that your partialTriggers are set up correctly so that the <af:messages> tag is re-evaluated.

Anyway, the demo code is available here.  Enjoy.

Note: The demo will only run in 11.1.1.7  and 11.1.2..3 + but the message checking code part will run in earlier versions as well.  It's just that the demo screen uses the new panelGridLayout. 

Wednesday May 22, 2013

UKOUG ADF Mobile Demo

Yesterday I participated in a Special Interest Group meeting organised by the UK Oracle User Group on ADF Mobile. 

As part of my session I concentrated on building an ADF Mobile application from the ground up based on grabbing JSON data from Hudson. This demo shows the core techniques for dealing with URL based data and parsing the same. Several folks at the event had asked for the demo code so I've packaged and uploaded onto the ADF EMG Code Samples Repository:

Enjoy!

Friday May 17, 2013

Launching JConsole as an External Tool From JDeveloper

I find JConsole to be a useful tool, particularly for MBean browsing, but frankly getting the correct command line arguments to get it to connect correctly to my WebLogic instances is a bit of a pain. I always have to go and look it up. - generally from here. However, setting all those paths is tedious. Given that I'm usually working in an environment where my JDeveloper, and the WebLogic servers I'm using JConsole on, are matched from a version perspective I can get JDeveloper's external tools capability to do the lifting.

Very simple this. Just choose Tools > External Tools from the menu and press New.  Then run through the wizard:

  1. Type is External Program
  2. Program Options > Program Executable = jconsole 
  3. Program Options > Arguments =  (All on one line of course, reformatted here for readability)
 -J-Djava.class.path=${java.path}/lib/jconsole.jar:
                     ${java.path}/lib/tools.jar:
                     ${prop:name=weblogic.home}/lib/wljmxclient.jar 
 -J-Djmx.remote.protocol.provider.pkgs=weblogic.management.remote 

And that's it.  JDeveloper helpfully substitutes both the Java location and the WebLogic location for us saving all that hunting around.  

Tip

 Thanks to Torsten Kleiber who discovered and followed up on the twist of ${java.path} not expanding correctly (or rather expanding to null). Before running the tool command with the macro make sure that you have a project open and selected as the actual java path is obtained in the context of the JRE version used by the selected project. (Project Properties > Libraries and Classpath > Java SE Version)


Wednesday May 15, 2013

Conveyor Visualization for Tabs in ADF

If you look carefully at the online demos for panelTabbed in 11.1.1.7 you may notice that the tabs are sporting a slightly changed UI for situations where the number of tabs can't fit into the available horizontal space. 

Here's the situation with the default representation of a tab-set when it overflows. The chevron  on the right of the tab-set can be clicked to display a drop-down list of the remaining tabs. 

Basic tab visualization

In 11.1.1.7 we now have an alternative visualization where the hidden tabs are available on a conveyor belt and the user can scroll along the belt rather than having to use the pull-down list.

Conveyor Tabs

Enabling this feature

This visualization is not controlled by any property on the component but rather is switched on through the skin being used in the application. As such, all tab-sets within the application will gain the visualization if it is switched on. 

To enable it you will need to create a custom skin, if you are not familiar with  process then there are plenty of articles and documentation out there to help you, or you can download the demo that I've created to go along with this article. Basically I've created a custom skin that extends the new Skyros skin that 11.1.1.7 uses by default, and plugged that in to replace Skyros.

Within the skin file there is a single entry to make for panelTabbed (and a similar one for navigationPane):

 af|panelTabbed {
    -tr-layout-type:conveyor; 
}

And that's it, as simple as that.  As I mentioned you can download a simple sample (DRM009) which shows this in action from the ADF EMG Demos Site

Friday May 03, 2013

Slide, Charlie Brown! Slide!

Following on from an earlier article(Using inputNumberSlider with Dates) where I showed you how you could use an <af:inputNumberSlider> to display formatted date strings rather than numbers, I've been expanding into other uses for the slider components. 

Specifically the most recent use case  was to represent text labels for the number "stops" on the slider so that it could be used as a way of filtering datasets. So this is what it looks like:

So, no problem you say, the previous article shows pretty much how to do that - why a new one?   Well the twist here is in the form of tables.

What if I want to use the slider in a table, and I want to have different slider labels for different rows, like this:

Well that's a bit more of a problem.  Why you ask?  It's because of the way that tables work.  When you define a table, each row is stamped out from the same set of components.  So If I have one converter that say converts numbers to  Domain, Kingdom, Phylum etc. associated with the slider then that's the converter that I'm going to use for every row as it's stamped out. I can't use a different converter per row. (Well OK I could use EL to specify a different converter value for each but then I'd need to define as many converters as I have value lists and plus I would have to know in advance what all the possible lists of filter values are.  In this case, the reality is that the values shown in the sliders come from user configuration rather than being baked into the application anyway, so a hardcoded solution is out) . 

So my aim here was to build a converter that could be used generically with as many different lists as required. You can download the resulting code from here.

If you take a look at the demo you will see that the converter is defined by name in the faces-config.xml  and then associated with the inputSlider

<af:inputNumberSlider value="..." minimum="0" maximum="3" minorIncrement="1" 
                      converter="ismsConverter">
    <f:attribute name="imsConverterMeasureElements" value="John,Paul,Ringo,George"/>
</af:inputNumberSlider> 

The actual list of elements which will be displayed as labels for each slider stop are then passed as a comma delimited string using the <f:attribute> tag.

This version of the converter always assumes a zero indexed list and the labels are assigned in order from zero. So selecting George in the slider above will translate into a value of 3. It would be perfectly possible to adapt the code to allow specific mapping between a number and the label, e.g. if you wanted a 1 based list you might pass a definition string like this:

"1:John,2:Paul,3:Ringo,4:George"

You'd just need to do a little more parsing in the converter itself to make this work though.

Even with no change you can use the converter out of the box with <af:inputRangeSlider>. Here's a version with Roman numerals:

 Finally on the matter of datatypes there is a slight twist when using a model attribute of type oracle.job.domain.Number.  The ismsConverter will handle the basic Java types, float, int, long double etc. and then there us a second converter called ismsJboConverter that handles the JBO Number type.  All of this is shown in the demo.

Tuesday Apr 30, 2013

New Table Sorting Capability in Patchset 6

With every new release you can trawl through the release notes and fine some handy new features to play with, however, sometimes there is even more to discover hidden away.

One such feature, which I think is actually pretty exciting, has crept into the 11.1.1.7.0 release of JDeveloper / ADF.  This is a new feature which adds case insensitive sorting to the table.  Previously we have had to resort to tricks such as defining transient attributes where all attributes are converted to a particular case in order to create this transient attribute. It would then be used as the sortProperty on the <af:column> that houses the column that you wanted to sort in a case insensitive way.  Not too difficult to do, but it means adding stuff to your model to satisfy a UI need. Now there is a cleaner way.

So to replace this technique, we now have a new property on <af:column> called sortStrength. This new property takes one of four values which allow you some degree of control as to how the sorting takes place. The resulting sorts are locale specific.  This is probably best illustrated with a table:

Identical (default)  This is the default value and reflects the traditional behavior where the sort is very sensitive. i.e AA != aa and aa != áá
Primary  Only the primary difference is observed i.e. the underlying letter. So a != b of course but AA == aa == áá == Äæ  for the purposes of sort. You can think of this as the most promiscuous sort   
Secondary Secondary is still case insensitive. A secondary difference is something like an accented version of a character. So in this case AA == aa, however, aa != áá.  
Tertiary

 Returns us to the world of case sensitivity, so AA != Aa != áá != ÁÁ.  There are some subtle locale specific differences between Identical and Tertiary but for most purposes they will have the same effect

 So you can see that for day-to-day case insensitive table sorting you should use the Primary or Secondary values depending on how you want to treat accented characters.  If you are wondering where the weird Primary, Secondary, Tertiary thing came from, head over to the JavaDoc for the java.text.Collator class which is the mechanism underlying all of this. 

 

 

About

Hawaii, Yes! Duncan has been around Oracle technology way too long but occasionally has interesting things to say. He works in the Development Tools Division at Oracle, but you guessed that right? In his spare time he contributes to the Hudson CI Server Project at Eclipse
Follow DuncanMills on Twitter

Note that comments on this blog are moderated so (1) There may be a delay before it gets published (2) I reserve the right to ignore silly questions and comment spam is not tolerated - it gets deleted so don't even bother, we all have better things to do with our lives.
However, don't be put off, I want to hear what you have to say!

Search

Archives
« April 2014
MonTueWedThuFriSatSun
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    
       
Today