Monday Dec 17, 2012

Accessing ADF Faces components that are read-only from JavaScript

Almost as a note to myself and to justify the time I spent on analyzing aproblem, a quick note on what to watch out for when working trying to access read-only ADF Faces components from JavaScript. 

Those who tried JavaScript in ADF Faces probably know that you need to ensure the ADF Faces component  is represented by a JavaScript object on the client. You do this either implicitly by adding an af:clientListener component (in case you want to listen for a component event) or explicitly by setting the ADF Faces component clientComponent property to true.

For the use case I looked at in JDeveloper 11g R1 ( I needed to make an output text component clickable to call a JavaScript function in response. Though I added the af:clientListener tag to the component I recognized that it also needed the clientComponent property set to true.

Though I remember this as not being required in, I like the new behavior as it helps preventing read-only components from firing client side events unless you tell it to do so by setting the clientComponent property to true.

Note: As the time of writing, JDeveloper is not publicly available and I put the note in this blog as a reminder in case you ever hit a similar challenge so you know what to do.

Thursday Mar 08, 2012

Using af:serverListener as a JS client-server proxy

Despite of ADF Faces having a client side JavaScript architecture, JavaScript rule #1 in ADF Faces is to use JavaScript as a fallback option only for development use cases in which there is no native solution to a problem. A built-in feature of the ADF Faces JavaScript client architecture is security that disallows certain component properties like disabled and readOnly to be changed from JavaScript.

To quote the JavaScript doc for the AdfRichInputText object:

public Boolean getReadOnly()

Get function for attribute for 'readOnly'. This attribute is secured. You may get it, but you may not set it. Any changes to this attribute will not be transmitted to the server.

Note: The disabled property can be enabled for JavaScript modification by setting the component unsecure property as explained in the component documentation, which however I don't recommend you to do. If you need to open protected features for modification, do so in a way that you control, for example in that you can check a user permission to do so.

There might be use cases in which you need to change a protected property from JavaScript, and here is how this can and should be done:

The ADF Faces af:serverListener component allows developers to invoke server side Java from JavaScript and thus can be used as a proxy to bypass applied client side security.

For example, to be able to change the readOnly property on an af:inputText component, you define the text field as shown below

<af:inputText label="Label 2"
              <af:serverListener type="serverAction"

The clientComponent property need to be set to true on the component to ensure a JavaScript object is created on the client architecture. With no clientComponent set to true and no af:clientListener attached, the text field component is not accessible from JavaScript at all.

The af:serverListener needs to be configured on the component that is passed as a component reference to the server. In the sample, the component reference that is sent to the server is the input text field that you want to switch from updateable to read-only. If the integration is from a non ADF Faces component, like an Applet, you would configure the af:serverListener on the af:document component. If this is the case, you may not make use of the component reference on the server and instead pass additional payload arguments.

In the Oracle JDeveloper sample to this article the switch between read-only and updateable is simulated by a command button you can press. The sample can be dowloaded from here.

In a realistic use case, this switch would be triggered from a non ADF Faces component like Applet or another technology you integrate in your ADF Faces page.

Note: The use of a command button in the sample is only for demonstration purpose. If the trigger was a command button then no JavaScript would be needed at all and JavaScript rule #1 would apply

On the server, a managed bean method is invoked by the client JavaScript call shown below:

<af:resource type="javascript">
  function setUpdateable(actionEvent){
     var commandButton = actionEvent.getSource();
     var textFieldId = commandButton.getProperty('componentId');
  function setReadOnly(actionEvent){      
    var commandButton = actionEvent.getSource();
    var textFieldId = commandButton.getProperty('componentId');
  function invokeServerAction(compId,evt,isUpdateable){
    var textField = evt.getSource().findComponent(compId);            
         {updateable: isUpdateable},false);                              

Note: payload arguments are surrounded by curly braces. If you want to pass multiple arguments then you use a comma separated list of key1:value1, key2:value2 …pairs.

The JavaScript is taken from the sample provided for this tip and – as mentioned – is invoked from a command button. The command button has a custom property (af:clientAttribute) added that tells the script about the text component Id to modify. The component and the desired switch state "readOnly" or "updateable" is passed to the managed bean method:

  * Proxy the client request
  * @param clientEvent The client event gives you access to the 
  * component that raises the event as well as to the paraneters 
  * passed from the client to the server 
 public void actionEvent(ClientEvent clientEvent) {
   * This would be a good place to check an ADF Security resource
   * permission if the user is allowed to perform the change on the 
   * attribute. There is no security in JavaScript, but using server 
   * side JAAS protects you from unauthorized changes
   RichInputText inputText =  (RichInputText) clientEvent.getComponent();
   String updateable = (String) clientEvent.getParameters().get("updateable");
   AdfFacesContext adfFacesContext = AdfFacesContext.getCurrentInstance();

Sample Download


A blog on Oracle JDeveloper, ADF, MAF, MCS and other mobile and web topics inspired by questions and answers posted on the OTN forums.

Frank Nimphius


« July 2016