Monday, April 22, 2019

How to support Arabic characters in Jdeveloper 12c


How to support Arabic characters in Jdeveloper

Go to Preferencesè EnvironmentèSet Encoding to UTF-8


Click Ok and restart jdeveloper

You should be able to get the jdeveloper now supporting any unicode character.



Monday, July 27, 2015

How to enable Prime Faces latest community edition in Oracle ADF essentials version-12c?


Recently faced a requirement from client that existing ADF essentials application need to run on Stand Alone Kiosk which did not have keyboard support. Since Oracle’s ADF components do not come with in-built virtual keyboard had to search a lot and came to a conclusion that we have.

Following best ways of implemting desired functionality
1. Custom JavaScript driven keyboard.
2. JQuery virtual keyboard.
3. Prime faces Keyboard component.

Since prime faces is also JSF based component suite I decided to give it a try and following steps helped me actually in integrating both component suites.

1. Download primefaces-5.2.jar community edition from prime faces download site http://primefaces.org/downloads
2. Copy downloaded file to your project’s WEB-INF\lib directory
3. Add this downloaded jar file to  project properties using Jdeveloper.
4. Once you do this you will see the Prime faces library listed in component window.
5. You can now drag drop components in source mode of your JSF page.


You can have look at the below code for reference

primedemo.jsf

<af:document title="primedemo.jsf" id="d1">
        <af:form id="f1">
            <af:panelStretchLayout id="psl1" inlineStyle="width:inherit;">
                <f:facet name="bottom"/>
                <f:facet name="center">
                    <af:panelGroupLayout id="pgl1" layout="scroll" inlineStyle="width:inherit;">
                        <primefaces-p:keyboard id="k1" binding="#{backingBeanScope.primedemo_backing.keyboardvalue}"/>
                        <af:button text="Show" id="b1"
                                   actionListener="#{backingBeanScope.primedemo_backing.buttonActionListener}"/>
                    </af:panelGroupLayout>
                </f:facet>
                <f:facet name="start"/>
                <f:facet name="end"/>
                <f:facet name="top"/>
            </af:panelStretchLayout>
        </af:form>
    </af:document>


primedemo_backing.java
package view;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import org.primefaces.component.keyboard.Keyboard;

public class primedemo_backing {
    private Keyboard keyboardvalue;

    public primedemo_backing() {
    }

    public void setKeyboardvalue(Keyboard keyboardvalue) {
        this.keyboardvalue = keyboardvalue;
    }

    public Keyboard getKeyboardvalue() {
        return keyboardvalue;
    }

    public void buttonActionListener(ActionEvent actionEvent) {
        // Add event code here...
        FacesMessage Message = new FacesMessage(String.valueOf(keyboardvalue.getValue()));  
              Message.setSeverity(FacesMessage.SEVERITY_INFO);  
              FacesContext fc = FacesContext.getCurrentInstance();  
              fc.addMessage(null, Message);  
       
    }

}

Versions Used
1.Oracle Jdeveloper 12.1.3
2.PrimeFaces community edition version primefaces-5.2.jar

Cheers 


Thursday, January 2, 2014

Integrate Apache SHIRO With ADF 11g (RichClient/Trinidad)


 Apache Shiro basics

Shiro is a project with a long history—it started life as JSecurity back in 2003 when there were really few options for Java security. It provides four main pieces of functionality:
• Authentication
• Authorization
• Cryptography
• Session management
We'll be using the authentication part (determining who the user is) and the authorization part (determining what the user can do). We will not be using the cryptography (encrypting and decrypting data)
or the session management (we rely on standard JSF and ADF functionality for
our session data).

Getting the software
You can download the Shiro software from http://shiro.apache.org. You'll want the Latest Stable Release, Binary Distribution. Download the shiro-core and shiro-web JAR files. Because you don't want your application to depend on a directory outside the application structure, create a directory called extjars in the application directory and place your JAR files there. The Shiro code uses Simple Logging Façade for Java (SLF4J), so you also need to download SLF4J from http://www.slf4j.org. Download the ZIP file, unpack it somewhere, and copy the slf4j-api-1.7.5.jar and slf4j-simple-1.7.5.jar files to the same directory. If a newer version than 1.7.5 is available by the time you read this, use that instead.



Installing the packages in your application
To use Shiro security in your application, you need to include the JAR files in your project. To do this, choose Project Properties for your View project and then Libraries and Classpath. Click on Add Library and then New. Give your library the name Shiro and choose Location as Project. Then select the Class Path node in the tree, click on Add Entry, and add the four JAR files. Remember to check the Deployed by Default checkbox 



The Deployed by Default checkbox indicates that these libraries should be deployed with the application. If you don't select this box, your application EAR file gets smaller, but you have to ensure that the libraries are available on each server you deploy it to.

Click on OK several times to return to the application.

Now we have the JAR files ready for use in our application, but we also need to actually configure the application to use them. So, we add a servlet filter so that every request for a page of our application is passed through Shiro. This allows Shiro to perform security evaluation before the page is shown to the user.

To add this filter, we change the web.xml file. You can find this file in your View project under Web Content | WEB-INF. When you double-click on the file, JDeveloper opens it in a specialized editor that allows you to change all settings through user-friendly dialog boxes. In this case, however, we will use the Source view to work directly with the file. Click on the Source tab at the bottom of the web.xml window and insert the following code:         


 <context-param> 
      <param-name>shiroConfigLocations</param-name> 
      <param-value>/WEB-INF/shiro.ini</param-value> 
 </context-param> 

<listener>

<listener-class>
org.apache.shiro.web.env.EnvironmentLoaderListener
</listener-class>
</listener>

<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter
</filter-class>
</filter>

<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>


The <listener> element goes with the other <listener> elements, and the filter/ filter-mapping block goes between the last existing <filter> and the first existing <filter-mapping>.

By placing your Shiro filter mapping first in the file, this filter is applied first at runtime. There is no need to apply the other filters if Shiro figures out that the user doesn't have access anyway



Configuring your application for Shiro

Shiro is configured through the use of a Shiro INI configuration file. Create a new file (item type File in the New dialog), call it shiro.ini, and place it in the /WEB-INF directory of the view project


Contents of shiro.ini (For rich client application)
[main]
user = sbaf.view.rc.shirofilter.FacesAjaxAwareUserFilter
shiro.loginUrl = /faces/infrastructure/SLogin.jsf
user.loginUrl =  /faces/infrastructure/SLogin.jsf

# DataSource config
ds = org.apache.shiro.jndi.JndiObjectFactory
ds.requiredType = javax.sql.DataSource
ds.resourceName = jdbc/PWCMMISDS
# JDBC realm config
jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.permissionsLookupEnabled = true
# Configure JDBC realm SQL queries.
jdbcRealm.authenticationQuery = SELECT ADUM_PASSWORD FROM ad_user_mst WHERE ADUM_USER_ID = ?
jdbcRealm.userRolesQuery = SELECT ADUR_ROLE_ID FROM ad_user_roles WHERE ADUR_USER_ID =?
jdbcRealm.permissionsQuery = SELECT 1 FROM dual
jdbcRealm.dataSource = $ds

[urls]
/faces/infrastructure/SLogin.jsf = user
/faces/common/welcome.jspx = user
/faces/** = user

Contents of shiro.ini for Trinidad Application
[main]
user = sbafuserinterfaces.FacesAjaxAwareUserFilter
shiro.loginUrl = /faces/infrastructure/SLogin.jspx
user.loginUrl =  /faces/infrastructure/SLogin.jspx

# DataSource config
ds = org.apache.shiro.jndi.JndiObjectFactory
ds.requiredType = javax.sql.DataSource
ds.resourceName = jdbc/cgmandiDS
# JDBC realm config
jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.permissionsLookupEnabled = true
# Configure JDBC realm SQL queries.
jdbcRealm.authenticationQuery = SELECT ADUM_PASSWORD FROM ad_user_mst WHERE ADUM_USER_ID = ?
jdbcRealm.userRolesQuery = SELECT ADUR_ROLE_ID FROM ad_user_roles WHERE ADUR_USER_ID =?
jdbcRealm.permissionsQuery = SELECT 1 FROM dual
jdbcRealm.dataSource = $ds

[urls]
/faces/infrastructure/SLogin.jspx = user
/faces/common/welcome.jspx = user
/faces/** = user

Note:- Datasource Name can vary with respect to what you configure in your application

Form-based authentication
If we want our own login page, we need to build it. In other contexts, it is possible to use a simple HTML-based login page with Shiro, but for an ADF application where we use JSF, we need to create a JSF login page and a backing bean to perform the actual login operations

The login bean
  Create a new java class “SecurityHandlerBean” and place that under the package sbafuserinterfaces. If this is rich client application configure this bean using adfc-config.xml. If you are using Trinidad then configure this bean in faces-config.xml

Source code of the class:-

package sbafuserinterfaces;
import java.io.IOException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.ArrayList;
import javax.faces.application.FacesMessage;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
import javax.servlet.http.HttpServletRequest;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.web.util.SavedRequest;
import org.apache.shiro.web.util.WebUtils;
import sun.misc.BASE64Encoder;
public class SecurityHandlerBean {
    private String userName;
    private String password;
    private String encpassword;
    private ArrayList<String> languageList=new ArrayList<String>();
    private String selectedLanguage="en";   
    private boolean remember;
    public static final String HOME_URL = "/faces/common/welcome.jspx";
    public static final String LOGIN_URL = "Slogin.jsf";
    public SecurityHandlerBean() {
    }
    public boolean isUserAllowedToSeeAddress() {
        return SecurityUtils.getSubject().isPermitted("ViewAddress");
    }
    public String login() {
        try {
            encpassword=getKeyDigestString(password,null);
            System.out.println(encpassword);
            SecurityUtils.getSubject().login(new UsernamePasswordToken(userName, encpassword, remember));
            HttpServletRequest request =
                (HttpServletRequest)(FacesContext.getCurrentInstance().getExternalContext().getRequest());
            SavedRequest savedRequest = WebUtils.getAndClearSavedRequest(request);
            ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
            if (savedRequest != null) {
                System.out.println("SavedRequest URL:" + savedRequest.getRequestUrl());
            }
          //  externalContext.redirect(savedRequest != null ? savedRequest.getRequestUrl() : HOME_URL);
     
          externalContext.redirect( request.getContextPath()+HOME_URL);
        } catch (Exception e) {

            FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR,"Sorry, failed to validate you. Please try again", "");
            FacesContext.getCurrentInstance().addMessage(null, msg);
            e.printStackTrace(); // TODO: logger.
        }
        return "";
    }

    String getAbsoluteApplicationUrl() throws Exception {
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        HttpServletRequest request = (HttpServletRequest)externalContext.getRequest();
        URL url = new URL(request.getRequestURL().toString());
        URL newUrl = new URL(url.getProtocol(), url.getHost(), url.getPort(), request.getContextPath());
        return newUrl.toString();
    }
    public String logout() throws IOException {
        SecurityUtils.getSubject().logout();
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        externalContext.invalidateSession();
        // externalContext.redirect(LOGIN_URL);
        return "logout";
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserName() {
        return userName;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getPassword() {
        return password;
    }
    public void setRemember(boolean remember) {
        this.remember = remember;
    }
    public boolean isRemember() {
        return remember;
    }
    public String getKeyDigestString(String message, String key) throws NoSuchProviderException {
        try {
            String pwCompareStr = "";
            byte[] messageByte = message.getBytes();
            // if no key is provided, the message string gets encrypted with itself
            byte[] keyByte = (key != null && key.length() > 0) ? key.getBytes() : message.getBytes();
            // get SHA1 instance      
            MessageDigest sha1 = MessageDigest.getInstance("SHA-1", "SUN");
            sha1.update(messageByte);
           
            //byte[] digestByte = sha1.digest(keyByte);
            byte[] digestByte = sha1.digest();

            // base 64 encoding
            BASE64Encoder b64Encoder = new BASE64Encoder();
            pwCompareStr = (b64Encoder.encode(digestByte));
            pwCompareStr = new StringBuilder("{SHA-1}").append(pwCompareStr).toString();
            return pwCompareStr;
        } catch (NoSuchAlgorithmException e) {
        }
        return null;
    }   
    public void languageChangeEvent(ValueChangeEvent valueChangeEvent){
      
    }
    public void setLanguageList(ArrayList<String> languageList) {
        this.languageList = languageList;
    }
    public ArrayList<String> getLanguageList() {
        return languageList;
    }
    public void setSelectedLanguage(String selectedLanguage) {
        this.selectedLanguage = selectedLanguage;
    }

    public String getSelectedLanguage() {
        return selectedLanguage;
    }   
}

Ensure that the user id and password fields value property is bind to the configured LoginBean corresponding property.

The login page
  Create new page as per the technology stack (Richclient/Trinidad) and place that in

Sample Login page (Trinidad)
<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1" xmlns:f="http://java.sun.com/jsf/core"
          xmlns:h="http://java.sun.com/jsf/html" xmlns:trh="http://myfaces.apache.org/trinidad/html"
          xmlns:tr="http://myfaces.apache.org/trinidad">
    <jsp:output omit-xml-declaration="true" doctype-root-element="HTML"
                doctype-system="http://www.w3.org/TR/html4/loose.dtd"
                doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"/>
    <jsp:directive.page contentType="text/html;charset=UTF-8"/>
    <f:view>
        <trh:html>
            <trh:head>
                <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
            </trh:head>
            <trh:body>
                <h:form>
                    <tr:panelFormLayout maxColumns="1" rows="3">
                       <tr:inputText label="UserId" value="#{LoginBean.userName}" autoSubmit="true"/>
                        <tr:inputText label="Password" secret="true" value="#{LoginBean.password}" autoSubmit="true"/>
                        <tr:commandButton text="Login" action="#{LoginBean.login}"/>
                        <f:facet name="footer"/>
                    </tr:panelFormLayout>
                </h:form>
            </trh:body>
        </trh:html>
    </f:view>
</jsp:root>
Sample Login page (RichClient)
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
    <af:document title="Login" id="d1">
        <af:form id="f1">
         <af:panelStretchLayout id="psl1" dimensionsFrom="auto">
              <f:facet name="bottom"/>
              <f:facet name="center">
               <af:panelGroupLayout id="pgl2" layout="vertical" valign="middle" halign="center">
                <af:spacer width="10" height="150"/>
                <af:panelBox text="" id="pb1" showDisclosure="false" inlineStyle="width:300px; height:250.0px;"
                             rendered="true">
                    <af:panelFormLayout id="pfl1">
                      <af:inputText label="User Name" id="it1" autoSubmit="true"
                                    value="#{SLoginbean.userName}"
                                    partialTriggers="cb1 cb2"/>
                      <af:spacer width="10" height="10"/>
                      <af:inputText label="Password" id="it2" secret="true" autoSubmit="true"
                                    value="#{SLoginbean.password}"
                                    partialTriggers="cb1 cb2"/>
                      <af:spacer width="10" height="10"/>
                      <af:selectOneChoice label="Language"
                                          value="#{SLoginbean.selectedLanguage}"
                                          valueChangeListener="#{SLoginbean.languageChangeEvent}"
                                          id="soc1" autoSubmit="true">
                        <af:selectItem label="Arabic" value="ar" id="si3"/>                                         
                        <af:selectItem label="Hindi" value="hi" id="si2"/>
                        <af:selectItem label="English" value="en" id="si1"/>
                      </af:selectOneChoice>
                     <af:spacer width="10" height="10"/>
                      <f:facet name="footer">
                       <af:panelGroupLayout id="pgl12" layout="vertical" halign="center">
                       <af:spacer width="10" height="10"/>
                        <af:panelGroupLayout id="pgl1" layout="horizontal" halign="center">
                        <af:commandButton text="Login" id="cb1" partialSubmit="true"
                                          action="#{SLoginbean.login}">
                        </af:commandButton>
                        <af:spacer width="10" height="10"/>
                        <af:commandButton text="Cancel" id="cb2" rendered="false"/>                       
                      </af:panelGroupLayout>
                      </af:panelGroupLayout>
                      </f:facet>
                    </af:panelFormLayout>
                </af:panelBox>
              </af:panelGroupLayout>
              </f:facet>
              <f:facet name="start"/>
              <f:facet name="end"/>
              <f:facet name="top"/>
            </af:panelStretchLayout>
        </af:form>
    </af:document>
</f:view>



The user filter
Because Shiro was born in the classic HTML and JSP world, it doesn't really understand all the asynchronous JavaScript used in a modern JSF application. This means that we cannot use a plain Shiro UserFilter filter to redirect to the login page, but we instead need to build our own. Fortunately, JEE developer Bauke Scholtz has already figured out how to build such a filter, and he has documented it on his blog  http://balusc.blogspot.sg/2013/01/apache-shiro-is-it-readyfor-java-ee-6.html).

The following filter is verbatim the one he developed. Create a Java class called FacesAjaxAwareUserFilter in a new sbafuserinterfaces Java package under your application base package with content as follows:

package sbafuserinterfaces;
import java.io.IOException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.shiro.web.filter.authc.UserFilter;
public class FacesAjaxAwareUserFilter extends UserFilter {
    private static final String FACES_REDIRECT_XML =
        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<partial-response><redirect url=\"%s\"></redirect></partial-response>";
    @Override
    protected void redirectToLogin(ServletRequest req, ServletResponse res) throws IOException {
        HttpServletRequest request = (HttpServletRequest)req;
        if ("partial/ajax".equals(request.getHeader("Faces-Request"))) {
            res.setContentType("text/xml");
            res.setCharacterEncoding("UTF-8");
            res.getWriter().printf(FACES_REDIRECT_XML, request.getContextPath() + getLoginUrl());
        } else {
            super.redirectToLogin(req, res);
        }
    }
}


The logout Method
This logout method needs to be changed to the following piece of code so as to ensure that the shiro logout is invoked.
    public String logout_action()throws IOException {
        MpUsageLogView v_mplog = new MpUsageLogView();
        v_mplog.logUsage("Logout", "", "");       
        SecurityUtils.getSubject().logout();
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        HttpServletResponse response = (HttpServletResponse)externalContext.getResponse();
        HttpServletRequest req = (HttpServletRequest)externalContext.getRequest();
        externalContext.invalidateSession();
          try {
              response.sendRedirect((new StringBuilder()).append(req.getContextPath()).append("/faces/common/welcome.jspx").toString());
              FacesContext.getCurrentInstance().responseComplete();
          } catch (IOException e) {
          }       
                   return null;               
    }


The Weblogic.xml Changes
We need to comment out everything in Weblogic.xml. You will find below entries there. Comment them out
<security-role-assignment>
    <role-name>1</role-name>
    <principal-name>1</principal-name>
  </security-role-assignment>
  <security-role-assignment>
    <role-name>2</role-name>
    <principal-name>2</principal-name>
  </security-role-assignment>
  <security-role-assignment>
    <role-name>4</role-name>
    <principal-name>4</principal-name>
  </security-role-assignment>
  <security-role-assignment>
    <role-name>5</role-name>
    <principal-name>5</principal-name>
  </security-role-assignment>


Change Web.xml

In web.xml we need to comment out the traditional security constraints

<!--<security-constraint>
        <web-resource-collection>
            <web-resource-name>sbaf</web-resource-name>
            <url-pattern>/faces/common/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>5</role-name>
        </auth-constraint>
    </security-constraint>
   <login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
      <form-login-page>/faces/infrastructure/LoginNew.jspx</form-login-page>
      <form-error-page>/faces/infrastructure/LoginNew.jspx</form-error-page>
    </form-login-config>
  </login-config>
  <security-role>
        <role-name>1</role-name>
    </security-role>
    <security-role>
        <role-name>2</role-name>
    </security-role>
    <security-role>
        <description>4</description>
        <role-name>4</role-name>
    </security-role>
    <security-role>
        <description>CREATE_SESSION</description>
        <role-name>5</role-name>
    </security-role>
  <security-role>
    <role-name>valid-users</role-name>
  </security-role>-->



·         http://www.jobinesh.com/2013/02/securing-your-adf-applications-using.html (by Jobinesh Purushothaman)
·         Developing Web Applications with Oracle ADF Essentials by Sten E. Vesterli