Monday, April 27, 2015

ADF Skin

In this blog we are going to see how we can use ADF skin selectors to change look and feel of ADF pages. While going over this topic we will also try to see skinning framework of ADF

Here are the steps we are going to follow
1. Default page with input text.
2. Enable actual classes
3. How ADF is working
4. Derive ADF selector based on ADF classes
5. Register new skin
6. Modify ADF selector and see changes at runtime

1. Default page with input text: Lets create an ADF application with a page (MySkinPage.jsf). Add input text to page and see default skin in chrome.
 At runtime page looks like
We can notice few things here
a. ADF generates good amount of html for each ADF component.
b. It styles them by classes but name of these classes are very cryptic like .x25 or .xu

The cryptic class name is actually compressed class name, This makes our html and css code shorter and download time will be faster. Oracle generates these compressed class name at runtime. If we try to directly style these classes as x25/xu etc, we may lose context over time and even oracle may change these class names in future.

In ADF we put our styles against selector and framework reads these selector at runtime and create a class with compressed name. Our aim should be to provide styles against ADF selector.

But how to get actual selector that we should be modifying? One approach is read documentation http://jdevadf.oracle.com/adf-richclient-demo/docs/skin-selectors.html

Another approach could be to stop compression and ask framework to show actual (lengthier) class name. Using that class name we can try to derive selector name. To do this we can follow next step.

2. Enable actual classes: For this we just need to disable compression. We can do it easily by adding following lines in web.xml

<context-param>
         <param-name>org.apache.myfaces.trinidad.DISABLE_CONTENT_COMPRESSION</param-name>
         <param-value>true</param-value>
        </context-param>


As we are going to make changes in style sheet and we would love to see those changes immediately without any need to restart we can modify CHECK_FILE_MODIFICATION property of web.xml to true

<context-param>
         <param-name>org.apache.myfaces.trinidad.CHECK_FILE_MODIFICATION</param-name>
         <param-value>true</param-value>
        </context-param>

Run page and you should see actual class names.
3. How ADF is working
When you enable compression (default mode), ADF tries to convert your skin file and generate new skin file with shorter class names. It finds skin file (css) as configured in trinidad-config/trinidad-skin.xml file and then compress it. While compressing it generates a unique short class name for every valid adf selector. I said valid adf selector for example af|panelLabelAndMessage::content-cell.   You can refer http://jdevadf.oracle.com/adf-richclient-demo/docs/skin-selectors.html for all valid selectors.
Now when ADF generates HTML, it will used same compressed short unique names in html as well. For example if  af|panelLabelAndMessage::content-cell becomes "x1a2" in new compressed css, then html will also refer "x1a2" as class="x1a2".

When you disable compression then also ADF generates a new skin file. It converts ADF selectors to a valid class name. For example  af|panelLabelAndMessage::content-cell will become .af_panelLabelAndMessage_content-cell. Same thing will appear in html as well. Only thing compression will not happen so classes referred in new css and html are not compressed.

One common mistake is done by developers is to disable content compression for debugging and then directly use same style which is appearing in html in css file. For example if you disable compression, class is appearing in html as class="af_panelLabelAndMessage_content-cell". What you may be tempted to directly add below style in css file
.af_panelLabelAndMessage_content-cell {

}
You will see changes immediately and you happily forget about it. Later when you enable content compression, you find that style is no more working. Its because ADF will not compress .af_panelLabelAndMessage_content-cell. This is not valid selector. New CSS will have class as .af_panelLabelAndMessage_content-cell but your html component's class is compressed now.
Make a habit to derive selector name once you get ADF uncompressed class name.

4. Derive ADF selector based on ADF classes:
We can put styles in our css directly against .af_inputText  but that is not good practice as framework may changes these class names in future. What we want is to get a selector behind the class and then style that selector. We can always look for documentation and get correct selector. But following rules mostly work


 Example class
 Corresponding selector
 Rules applied
af_inputText
af|inputText
Change af_ to af|
af_inputText_label
af|inputText::label
Change af_ to af|
Change second _ to ::
af_inputText_content
af|inputText::content
Change af_ to af|
Change second _ to ::
Class inheritance
.af_inputText.p_AFDisabled .af_inputText_content
af|inputText:disabled::content
Change af| to af|
Change .p_AFDisabled to :disbaled
Change second _ from ::
[NOTE: inheritance is merged in single selector using : and ::]
 .af_button.p_AFTextOnly .af_button_text
 af|button:text-only::text
Change af| to af|
Change .p_AFTextOnly to :text-only
Change second _ from ::
[NOTE: inheritance is merged in single selector using : and ::]







I believe the documentation that we can refer to http://jdevadf.oracle.com/adf-richclient-demo/docs/skin-selectors.html

5. Register New Skin: You can follow blog http://sanjeev-technology.blogspot.in/2015/04/adf-do-you-know-oracle-provided-skins.html


6. Modify ADF selector and see changes at runtime: For this you just need to add selector entry in your css file and then change styles associated. for example

af|inputText::content
         {
           background-color: red;
         }
         

Note: In ADF we don't put entry of encrypted class or actual class name in css file. We try to set style for selector. At runtime Oracle convert these selectors to appropriate class name.

Friday, April 24, 2015

Sending email from APEX using APEX_MAIL

To send an email using APEX you can use APEX_MAIL.SEND and APEX_MAIL.PUSH_QUEUE apis

declare
    l_body      clob;
    l_body_html clob;
begin
    l_body := 'To view the content of this message, please use an HTML enabled mail client.' ;
    l_body_html := '<html><body><p> This is test email </p> </body></html>';
    APEX_MAIL.SEND (
        p_to        => 'fromemail@email.com',   -- change to your email address
        p_from      => 'toemail@email.com', -- change to a real senders email address
        p_body      => l_body,
        p_body_html => l_body_html,
        p_subj      => 'My subject' );

    APEX_MAIL.PUSH_QUEUE;


end;



Sunday, April 5, 2015

ADF: Do you know Oracle provided skins

Problem description: ADF application by default now renders in skyros skins. Before this it was FusionFx. Question is which all skins are provided by Oracle and how to see there look and feel. If we know them, then we can actually figure out which is best suited for us. In this blog I am going to show how do we get all skins provided by Oracle and how to use them in your project.

Solution: I would like to discuss about following topics
1. Overview of skins in ADF
2. trinidad-skins.xml
3. trinidad-config.xml
4. Oracle provided skins

-----------------------------------------------
1. Overview of skins in ADF: In normal web application we generally defind css file in <html> <head> section. In ADF we can always do that using af:resource tag but that may not be needed always. In ADF if we want to change (better to say extend) framework provided skins, we need to follow certain steps.
             a. Define a skin-family in trinidad-skins.xml
             b. Use skin-family using trinidad-config.xml
             c. Add ADF selectors in css file to create styles for ADF components.

2. trinidad-skins.xml: This file is used to define a css skin family. This file can be placed under src/META-INF directory of your UI project. To define a skin you need to use following

<?xml version="1.0" encoding="UTF-8" ?>
<skins xmlns="http://myfaces.apache.org/trinidad/skin">
  <skin>
    <id>sanstyle-v1.desktop</id>
    <family>sanStyle-v1</family>
    <version>
              <default>true</default>
              <name>v1</name>
    </version>
    <extends>fusionFx-v1.desktop</extends>
    <render-kit-id>org.apache.myfaces.trinidad.desktop</render-kit-id>
    <style-sheet-name>/skins/css/sanStyle-v1.css</style-sheet-name>
  </skin>
</skins>

It means you are defining a new skin family 'sanStyle-v1', which has css at '/skins/css/sanStyle-v1.css'. You need to create that css file in your project. It extends fusionFx-v1.desktop skin family, which means any styles defined in that css will automatically be included. You can definitely override those styles in your css 'sanStyle-v1.css' to create style specific to your need.

There are two ways to identify skin-family
a. Using <id> tag: id of a family must be unique. So you can identify a skin family using id.
b. Using <family> and <version> tags: <family> and <version> tags also form unique combination and it can also be used to identify skin-family.

We see there are two ways to identify skin-family. Now catch is when to use what.
Theare two use cases when we want to refer a skin-family
a. When we want to extend it and create new skin family: In this case we should use <id> tag
b. When we want application to pick css styles from a particular skin-family: In this case we need to specify skin-family in trinidad-config.xml, but we should use <family> and <version> tag to uniquely identify a skin-family.

3. trinidad-config.xml: Now you want to use this style. For that you need to have a trinidad-config.xml file in WEB-INF directory. Its by default created in ADF ViewController project.

If you see its default entry now a days pointing to skyros.

<trinidad-config xmlns="http://myfaces.apache.org/trinidad/config">
  <skin-family>skyros</skin-family>
  <skin-version>v1</skin-version>
</trinidad-config>

If you want to use sanStyle-v1, you can make entry something like
<trinidad-config xmlns="http://myfaces.apache.org/trinidad/config">
  <skin-family>sanStyle-v1</skin-family>
  <skin-version>v1</skin-version>
</trinidad-config>

4. Oracle provided skins
Before creating any custome skin family we should be knowing that which skin we should extend. And even at times we may want to directly use Oracle provided skin other than skyros-v1. To do that, we need to know which all skin families are provided by Oracle. One way to to read documentation but I believe better is just open oracle libraries.

a. Open 'ADF Faces Runtime 11' library in Jdeveloper
b. Open trinidad-skins.xml file and you will find all skin families provided by Oracle.
Few important entries are 


Family
Version
Extends
css
Usage in Trinidad-config.xml
skyros
v1
simple.desktop
adf/styles/skyros-v1-desktop.css
  <skin-family>skyros</skin-family>
  <skin-version>v1</skin-version>
fusionFx

fusion-11.1.1.3.0.desktop
adf/styles/fusionFx-v1-desktop.css
  <skin-family> fusionFx </skin-family>
fusionFx
v1.1
fusionFx-v1.desktop
adf/styles/fusionFx-v1.1-desktop.css
  <skin-family> fusionFx </skin-family>
  <skin-version>v1.1</skin-version>
fusion-simple

fusion-base.desktop
adf/styles/fusion-simple-desktop.css
  <skin-family> fusion-simple </skin-family>
fusionFx-simple

fusion-simple.desktop
adf/styles/fusionFx-simple-v1-desktop.css
  <skin-family> fusionFx-simple </skin-family>

Similarly there are other entries also.

You can even open css file and see different selectors.

Now you can try out different skin-family in trinidad-config.xml and see which skin is best for your project. 

If you want to view a look of each skin-family you need to change trinidad-config.xml entry. Any change in this file will require a re-deployment. To avoid redeploymenet you can put expression in trinidad-config.xml as


<trinidad-config xmlns="http://myfaces.apache.org/trinidad/config">
  <skin-family>#{param.skinFamily}</skin-family>

</trinidad-config>

Now in url pass skinFamily=<familyName> and you will see page in that skin-family.
For example 
http://<server:port>/<context>/faces/<page.jspx>?skinFamily=fusionFx  will render page in fusionFx skin and
http://<server:port>/<context>/faces/<page.jspx>?skinFamily=skyros will render page in skyros skin.