Mostrando entradas con la etiqueta ADF. Mostrar todas las entradas
Mostrando entradas con la etiqueta ADF. Mostrar todas las entradas

10 oct 2013

View SiteStudio Dynamic List on WebCenter Portal application

Last week my coworker Daniel wanted to view the results of a Dynamic List on a WebCenter Portal Content Presenter Template. After a few test we saw that this feature is not suppported.

Under a Content Presenter Template (CPT) you can show any field of the DataFile, simple text, WYSWYG, static list of elements, but seems that the Dynamic List was missing by WebCenter developers ;-)

To solve this issue we created a custom TaskFlow that is capable of listing the elements of a Dynamic List (Element Definition).

First I've created a new Element Definition (ED) of type "Dynamic List", this ED will perform this query:

dExtension <matches> `docx`

This will retrieve all Word documents of the WebCenter Content (WCC).

Next, I've created a Region Definition (RD) with two fields, one of type "Single Text" and another with the DynamicList (ED) just created.


After that, I've created a DataFile based on that Region Definition, this is the resulting XML content:


<wcm:root version="8.0.0.0" xmlns:wcm="http://www.stellent.com/wcm-data/ns/8.0.0">
  <wcm:element name="text">This is a simple text</wcm:element>
</wcm:root>

As you see, there is not track about the ED with the DynamicList, but if you edit that DataFile on WCC interface this is how it looks


So, where is the information of the "Documents" section stored? In the Element Definition called "ED-DYNLIST".

This is the content of the ED file:


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<elementDefinition xmlns="http://www.oracle.com/sitestudio/Element/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.oracle.com/sitestudio/Element/ http://www.oracle.com/sitestudio/ss_element_definition.xsd">
    <property value="3" name="type"/>
    <property value="" name="description"/>
    <complexProperty name="flags">
  ...
  ...
    </complexProperty>
    <property value="" name="height"/>
    <complexProperty name="dynlistaddregioncontent">
  ...
  ...
    </complexProperty>
    <dataProperty name="querytext">dExtension <matches> `docx`</dataProperty>
    <property value="dDocTitle" name="sortfield"/>
    <property value="asc" name="sortorder"/>
    <property value="20" name="resultcount"/>
    <property value="false" name="limitscope"/>
    <property value="" name="targetnodeid"/>
</elementDefinition>


As you see the query is stored on <dataProperty> TAG.

Now that we have all the needed information, we can create the TaskFlow that parses the WCC query stored on the ED file, and show the results of that query under a Content Presenter.

Diagram of our TaskFlow


This is how it looks like at the end



Download Links

Documentation

2 oct 2013

ADF Twitter timeline

Yesterday I was playing with twitter widgets, specifically I was trying to add the timeline to my blog, Is quite simple and these are the steps.

Log-in on your twitter account and go to "setup" menu item.



Now go to "Widgets" option and try to create a new one.


You can create timeline by user or by hashtag, in this example is created with #webcenter hashtag.


After the creation, the page will give you the HTML code to embed the timeline on your website. We have to look the <a> tag and save the "href" and "data-widget-id"

<a class="twitter-timeline" href="https://twitter.com/search?q=%23webcenter" data-widget-id="385306900536885248">Tweets sobre "#webcenter"</a>

Now we have the HTML to add the timeline in any page, but this won't work on an ADF application. Lets move this code to a TaskFlow, the first step is to create a JSF fragment for our taskflow that handles the HTML code provided by twitter. This is my fragment code:


<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1" xmlns:af="http://xmlns.oracle.com/adf/faces/rich" xmlns:trh="http://myfaces.apache.org/trinidad/html">
  <af:panelGroupLayout id="pgl1" layout="vertical">
    <a class="twitter-timeline" href="${pageFlowScope.href}" data-widget-id="${pageFlowScope.id}">Tweets by @${pageFlowScope.referer}</a>
    <trh:script generatesContent="true" id="jsTwitter">
    !function(d,s,id)
    {
        var js, fjs=d.getElementsByTagName(s)[0], p=/^http:/.test(d.location)?'http':'https';
        if(!d.getElementById(id))
        {
            js=d.createElement(s);
            js.id=id;
            js.src="https://platform.twitter.com/widgets.js";
            fjs.parentNode.insertBefore(js,fjs);
        }
    }
    (document,"script","twitter-wjs");
    </trh:script>
  </af:panelGroupLayout>
</jsp:root>

As you see, href and id are taskflow input parameters, when you add the taskflow on your page you have to add the parameters that were kept from last step.

Create a TaskFlow with the previous view as main view. Also add the both parameters as input for the taskflow.

After all, you only have to drop your TaskFlow as a region on a test page, this is my sample configuration:



Finally this is the result of the ADF TaskFlow after loading the twitter timeline.



Download the sample (link) and export as a ADF TaskFlow for the use on your ADF application.

27 may 2013

MouseOut close of ADF Popup with dialog inside.

A couple of months ago I was helping development of ADF 11g application. One of the most important parts of that app was the menu bar.

This menu was designed to support 4 levels, and almost 900 different options items. One of the problems that I faced was that some options of the menu opens a af:popup with an af:dialog inside. That options needs to be opened when user clicks, and self-closed when user moves out of dialog.

In summary, I need the mix of "mouseHover" and "action" types on my <af:showPopupBehavior> tag.

Check the following video to see the menu in action.



To modify the expected behavior of <af:showPopupBehavior> type "action" I've created this simple JavaScript function to overwrite ADF JS library.

AdfShowPopupBehavior.prototype.fire = function (a)
{
    a.cancel();
    var b = AdfPage.PAGE, c = this._type, d = a.getSource(), e = d.getClientId(), f = d.findComponent(this._popupId);
    if (AdfPage.PAGE.isScreenReaderMode() && (c == "mouseHover" || c == "mouseMove" || c == "mouseOver" || c == "mouseOut"))
    AdfLogger.LOGGER.fine("showPopupBehavior trigger type " + c + " suppressed in screen reader mode for launch source id: " + e);
    else if (f)
    {
        var g = f._delayedActivationState;
        if (g)
        if (g.launchSourceId == e)
            return;
        else 
        b.cancelTimer(g.timerId), 
        delete f._delayedActivationState;
        if (f.isPopupVisible())
        {
            var h = this._getPopupWindow(f);
            if (h == null)
            return;
            g = this._isInlinePopupSelector(h);
            h = this._wasOpendedFromSameSource(h, e);
            if (g)
            {
                if (f.hide(), h)
                    return 
            }
            else 
            h || f.hide()
        }
        var k = this._align, h = this._alignId, g = 
        {
        };
        g[AdfRichPopup.HINT_LAUNCH_ID] = e;
        var l = this._type == AdfComponentEvent.CONTEXT_MENU_EVENT_TYPE;
        if (h || k || l)
        {
            k && (g[AdfRichPopup.HINT_ALIGN] = k, h || (h = d.getClientId(), k = h.lastIndexOf(":"), k !=  - 1 && (h = h.substring(k + 1))));
            h && ((k = d.findComponent(h)) ? g[AdfRichPopup.HINT_ALIGN_ID] = k.getClientId() : AdfLogger.LOGGER.warning("Unable to find align component: ", h));
            if (l)
            g[AdfDhtmlPopupWindow.HINT_TYPE] = AdfDhtmlPopupWindow.HINT_TYPE_MENU, g[AdfDhtmlPopupWindow.HINT_AUTODISMISS] = AdfDhtmlPopupWindow.HINT_AUTODISMISS_MENU, h || (h = AdfAgent.AGENT.getMousePosition(a.getNativeEvent()), g[AdfDhtmlPopupWindow.HINT_MOUSEPOSITION] = h);
            if (c == "mouseHover" || c == "action")
            g[AdfDhtmlPopupWindow.HINT_AUTODISMISS] = AdfDhtmlPopupWindow.HINT_AUTODISMISS_MOUSEOUT, g[AdfDhtmlPopupWindow.HINT_AUTODISMISS_MOUSEOUT_ID] = g[AdfRichPopup.HINT_ALIGN_ID] ? g[AdfRichPopup.HINT_ALIGN_ID] : g[AdfRichPopup.HINT_LAUNCH_ID]
        }
        a.getType() == AdfUIInputEvent.MOUSE_IN_EVENT_TYPE ? (a = b.scheduleTimer(this, this._onMouseOverTimeout, 
        {
            hints : g, popup : f, source : d
        },
500), f._delayedActivationState = 
        {
            timerId : a, launchSourceId : e
        },
        d.addEventListener(AdfUIInputEvent.MOUSE_OUT_EVENT_TYPE, this._fireCancel, this)) : f.show(g)
    }
    else 
    AdfLogger.LOGGER.severe("Could not find popup ", this._popupId, " from component ", d)
};

The line that changes the expected behavior is this one:

if (c == "mouseHover" || c == "action")

Include that JS fragment in a JS file and later import to your pageTemplate or JSPX page:

<af:resource type="javascript" source="../js/popbehavior.js"/>

Also, you can modify the delay time of mouse-out event modifiying the "500ms" value in the JS code.

 Useful links

23 nov 2012

Showing first tab always in a ADF panelTabbed

Oracle ADF panelTabbed component has the capability of remember the last Tab that the user keeps opened.

When the user get back to the page or taskflow that contains the af:panelTabbed, the last tab opened will be shown instead of the first tab.

If you want to show always first tab as "opened", there is a couple of parameters at the af:showDetailItem that will help us.

This  is a sample code that will make the trick:

<af:panelGroupLayout id="pgl1" layout="vertical">
  <af:panelTabbed id="ptab1" position="above">
    <af:showDetailItem text="First" id="sdi1" persist="disclosed" disclosed="true"/>
    <af:showDetailItem text="Second" id="sdi2" persist="disclosed" disclosed="false"/>
    <af:showDetailItem text="Third" id="sdi3" persist="disclosed" disclosed="false"/>
  </af:panelTabbed>
</af:panelGroupLayout>  


 Check ADF Tag Library

Big thanks to my co worker María for finding the solution :-)

Download sample project

11 oct 2011

Speed up your JDeveloper for 64bit systems

This options will increase the performance of your JDeveloper under 64bit systems with 4 or more GB or RAM.

First locate the file jdev.conf (on my system is C:\Oracle\Middleware\jdeveloper\jdev\bin\jdev.conf)  and add this values:

#Extra tunning options
AddVMOption -XX:+AggressiveOpts
AddVMOption -XX:+UseStringCache
AddVMOption -XX:+OptimizeStringConcat
AddVMOption -XX:+ScavengeBeforeFullGC
AddVMOption -XX:+UseCompressedOops
AddVMOption -XX:+UseConcMarkSweepGC
AddVMOption -XX:+UseGCOverheadLimit

AddVMOption  -XX:MaxPermSize=800M

After that configure your JVM to use more memory

Under directory C:\Oracle\dev_home\system11.1.1.5.37.60.13\DefaultDomain\bin (or similar) the file setDomainEnv.bat (this only applies to 64 bit)
set XMS_SUN_64BIT=256
set XMS_SUN_32BIT=256
set XMX_SUN_64BIT=1024
set XMX_SUN_32BIT=512

Thats all, now your JDeveloper should be a bit faster 

:-)

22 ago 2011

Autenticación de PROXY NTLM en Weblogic

Recientemente estuve viendo como un simple proxy de salida de internet me estuvo dando problemas durante más de una semana para configurarlo en una aplicación web desplegada en Weblogic.


Recopilando un poco de información por internet por fin dimos con la clave para conseguir que la aplicación se conectara al exterior.


En primer lugar debemos de arrancar Weblogic con la variable de entorno PROXY_SETTINGS configurada. Esto hará que los script's de arranque del servidor de aplicaciones añaden dicha línea como parámetros de ejecución.


Ejemplo:

PROXY_SETTINGS="
-Dhttp.proxySet=true
-Dhttp.proxyHost=<proxy hostname o ip>
-Dhttp.proxyPort=<puerto proxy>
-Dhttp.proxyUser=<mi usuario>
-Dhttp.proxyPassword=<mi password>
-Dweblogic.webservice.transport.http.proxy.host=<proxy hostname o ip>
-Dweblogic.webservice.transport.https.proxy.host=<proxy hostname o ip>
-Dweblogic.webservice.transport.http.proxy.port=<puerto proxy>
-Dweblogic.webservice.transport.https.proxy.port=<puerto proxy>
-Dhttp.nonProxyHosts=\"localhost|127.0.0.1"
-DUseSunHttpHandler=true"



export PROXY_SETTINGS


De esta forma las variables de entorno están ya configuradas. Reiniciamos nuestro Weblogic o las ponemos en el propio script de arranque y reiniciamos.


Aparte de la configuración de Weblogic nos vimos obligados a incluir un código en nuestra aplicación que reescribia el authenticator del proceso Java que estaba corriendo en la JVM. Este paso sólo es necesario si tu aplicación utiliza tecnología ADF.


Antes de realizar una llamada HTTP invocaba el siguiente método:

//Proxy Weblogic
Proxy.getInstance().setup();


El código de la clase Proxy es:

public class Proxy
{
  private static final Logger logger = Logger.getLogger(Proxy.class);
  private static Proxy instance = null;
  private boolean enabled = false;


  public Proxy()
  {
    super();
  }


  public static Proxy getInstance()
  {
    if (instance == null)
      instance = new Proxy();


    return instance;
  }


  public void setup()
  {
    String proxySet = System.getProperty("http.proxySet");


    if (proxySet != null && proxySet.equals("true") && enabled == false)
    {
      String user = System.getProperty("http.proxyUser");
      String password = System.getProperty("http.proxyPassword");


      Authenticator.setDefault(new MyAuthenticator(user, password));
      logger.info("Proxy activado:" + proxySet);
      logger.info("Proxy usuario:" + user);
      logger.info("Proxy password:" + password);
      enabled = true;
    }
  }


  class MyAuthenticator extends Authenticator
  {
    private String username;
    private String password;


    public MyAuthenticator(String username, String password)
    {
      this.username = username;
      this.password = password;
    }


    public PasswordAuthentication getPasswordAuthentication()
    {
      return new PasswordAuthentication(username, password.toCharArray());
    }
  }
}