In some situations the business require that ADF application can connect to different database users depending on the login user. For example if user1 login, the ADF application will connect to database user hr/hr. If user2 login, the ADF application will connect to database user hr2/hr2.
This is call Dynamic JDBC.
In this url you can see how to apply this dynamic JDBC, but in my post I will simplify this url by creating a sample ADF application and go step by step for how to apply dynamic JDBC to this ADF application.
I use JDeveloper 11.1.2.4.0.
Note: From Step1 to Step5 it just steps for creating a simple ADF application. Applying the Dynamic JDBC to this simple application is starting from Step6.
Step1:
Create a simple ADF Application connect to "hr" database, this application will contains only 1 ViewObject (Employees) and will contains 2 jspx pages (login.jspx and emp.jspx)
Step2:
From faces-config.xml --> Navigation Rules define outcome to the two jspx pages.
login.jspx---> login
emp.jspx----> emp
Step5:
Run login.jspx page.
Now we have created a simple ADF application and we will now apply dynamic jdbc to this application.
Step6:
Open AppModule and set "Connection Type" to JDBC URL for both AppModuleShared and AppModuleLocal
Step7:
In the login button action we will store username/password it in session.
The login button action will be:
Step8:
Create new Filter (DynamicJDBCBindingFilter.java) extends ADFBindingFilter.
Step9:
Create Class (DynamicJDBCEnvInfoProvider) as
Step10:
Create Class (DynamicJDBCHttpSessionCookieImpl) as
Step11:
Create Class (DynamicJDBCSessionCookieFactory) as
Step12:
In web.xml update adfBindings and make it point to DynamicJDBCBindingFilter
then add filter mapping to adfBindings filter
Step13:
In AppModule update jbo.ampool.sessioncookiefactoryclass in AppModuleLocal and AppModuleShare to point to DynamicJDBCSessionCookieFactory
Step14:
Now run login.jspx and login with database username/password = hr/hr you will successfully login and get the data
Logout then login again with wrong password as hr/hr1 you will get "Invalid username/password".
You can download the sample application from here
This is call Dynamic JDBC.
In this url you can see how to apply this dynamic JDBC, but in my post I will simplify this url by creating a sample ADF application and go step by step for how to apply dynamic JDBC to this ADF application.
I use JDeveloper 11.1.2.4.0.
Note: From Step1 to Step5 it just steps for creating a simple ADF application. Applying the Dynamic JDBC to this simple application is starting from Step6.
Step1:
Create a simple ADF Application connect to "hr" database, this application will contains only 1 ViewObject (Employees) and will contains 2 jspx pages (login.jspx and emp.jspx)
Step2:
From faces-config.xml --> Navigation Rules define outcome to the two jspx pages.
login.jspx---> login
emp.jspx----> emp
Step3:
- In the login.jspx page add two inputTexts (Username and Password) and one command button for login.
- Bind Username inputText and Password inputText to the back bean.
- Create action for the login command button to read the username and password then navigate to emp.jspx page.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<af:document title="login.jspx" id="d1"> | |
<af:form id="f1" defaultCommand="cb1"> | |
<af:panelFormLayout id="pfl1"> | |
<af:inputText label="Username" id="it1" autoSubmit="true" binding="#{login.usernameComponent}"/> | |
<af:inputText label="Password" id="it2" autoSubmit="true" binding="#{login.passwordComponent}"/> | |
<f:facet name="footer"> | |
<af:commandButton text="Login" id="cb1" action="#{login.loginAction}"/> | |
</f:facet> | |
</af:panelFormLayout> | |
</af:form> | |
</af:document> |
Step4:
In the emp.jspx drag EmployeesView1 to the page and add logout link to the page
The back bean should be:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class LoginBean | |
{ | |
private RichInputText usernameComponent; | |
private RichInputText passwordComponent; | |
public LoginBean() | |
{ | |
} | |
public void setUsernameComponent(RichInputText usernameComponent) | |
{ | |
this.usernameComponent = usernameComponent; | |
} | |
public RichInputText getUsernameComponent() | |
{ | |
return usernameComponent; | |
} | |
public void setPasswordComponent(RichInputText passwordComponent) | |
{ | |
this.passwordComponent = passwordComponent; | |
} | |
public RichInputText getPasswordComponent() | |
{ | |
return passwordComponent; | |
} | |
public String loginAction() | |
{ | |
String username = (String) getUsernameComponent().getValue(); | |
String password = (String) getPasswordComponent().getValue(); | |
System.out.println("Username= " + username + " - Password= " + password); | |
return "emp";// | |
} | |
public String logoutAction() | |
{ | |
try | |
{ | |
FacesContext context = FacesContext.getCurrentInstance(); | |
HttpSession session = (HttpSession)context.getExternalContext().getSession(true); | |
if ( session != null ) | |
{ | |
session.invalidate(); | |
} | |
} | |
catch (Exception e) | |
{ | |
System.out.println("Session Invalidated..."); | |
} | |
return "login"; | |
} | |
} |
Run login.jspx page.
Now we have created a simple ADF application and we will now apply dynamic jdbc to this application.
Step6:
Open AppModule and set "Connection Type" to JDBC URL for both AppModuleShared and AppModuleLocal
Step7:
In the login button action we will store username/password it in session.
The login button action will be:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public String loginAction() | |
{ | |
String username = (String) getUsernameComponent().getValue(); | |
String password = (String) getPasswordComponent().getValue(); | |
System.out.println("Username= " + username + " - Password= " + password); | |
FacesContext ctx = FacesContext.getCurrentInstance(); | |
HttpSession session = (HttpSession) ctx.getExternalContext().getSession(true); | |
session.setAttribute("dbUser", username); | |
session.setAttribute("dbPassword", password); | |
return "emp";// outcome to emp.jspx page | |
} |
Step8:
Create new Filter (DynamicJDBCBindingFilter.java) extends ADFBindingFilter.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.IOException; | |
import javax.servlet.FilterChain; | |
import javax.servlet.ServletException; | |
import javax.servlet.ServletRequest; | |
import javax.servlet.ServletResponse; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.servlet.http.HttpSession; | |
import oracle.adf.model.servlet.ADFBindingFilter; | |
import oracle.jbo.JboException; | |
import oracle.jbo.client.Configuration; | |
public class DynamicJDBCBindingFilter extends ADFBindingFilter | |
{ | |
public DynamicJDBCBindingFilter() | |
{ | |
} | |
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException | |
{ | |
HttpSession session = ((HttpServletRequest) request).getSession(false); | |
if (session != null && session.getAttribute("loggedin") == null) | |
{ | |
String usrName = (String) session.getAttribute("dbUser"); | |
String pswd = (String) session.getAttribute("dbPassword"); | |
if (usrName != null && session.getAttribute("loggedin") == null) | |
{ | |
try | |
{ | |
if (usrName == null || usrName.length() == 0 || pswd == null || pswd.length() == 0) | |
{ | |
throw new JboException("Blank User name or Password"); | |
} | |
session.setAttribute(Configuration.DB_USERNAME_PROPERTY, usrName); | |
session.setAttribute(Configuration.DB_PASSWORD_PROPERTY, pswd); | |
super.doFilter(request, response, chain); | |
session.setAttribute("loggedin", "loggedin"); | |
} | |
catch (oracle.jbo.JboException e) | |
{ | |
try | |
{ | |
session.setAttribute("loggedin", null); | |
session.invalidate(); | |
} | |
catch (Exception e2) | |
{ | |
} | |
request.getRequestDispatcher("/faces/login.jspx").forward(request, response); | |
} | |
} | |
else | |
{ | |
super.doFilter(request, response, chain); | |
} | |
} | |
else | |
{ | |
super.doFilter(request, response, chain); | |
} | |
} | |
} |
Step9:
Create Class (DynamicJDBCEnvInfoProvider) as
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Hashtable; | |
import oracle.jbo.common.ampool.EnvInfoProvider; | |
import oracle.jbo.client.Configuration; | |
public class DynamicJDBCEnvInfoProvider implements EnvInfoProvider | |
{ | |
private final String mJDBCUserName; | |
private final String mJDBCPassword; | |
public DynamicJDBCEnvInfoProvider(String jdbcUserName, String jdbcPassword) | |
{ | |
mJDBCUserName = jdbcUserName; | |
mJDBCPassword = jdbcPassword; | |
} | |
public Object getInfo(String info, Object connEnvironment) | |
{ | |
if(mJDBCUserName != null) | |
{ | |
((Hashtable)connEnvironment).put(Configuration.DB_USERNAME_PROPERTY, mJDBCUserName); | |
} | |
if(mJDBCPassword != null) | |
{ | |
((Hashtable)connEnvironment).put(Configuration.DB_PASSWORD_PROPERTY, mJDBCPassword); | |
} | |
return null; | |
} | |
public void modifyInitialContext(Object p0) | |
{ | |
} | |
public int getNumOfRetries() | |
{ | |
return 0; | |
} | |
} |
Step10:
Create Class (DynamicJDBCHttpSessionCookieImpl) as
Step11:
Create Class (DynamicJDBCSessionCookieFactory) as
Step12:
In web.xml update adfBindings and make it point to DynamicJDBCBindingFilter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<filter> | |
<filter-name>adfBindings</filter-name> | |
<filter-class>view.DynamicJDBCBindingFilter</filter-class> | |
</filter> |
then add filter mapping to adfBindings filter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<filter-mapping> | |
<filter-name>adfBindings</filter-name> | |
<url-pattern>*.jsp</url-pattern> | |
<dispatcher>FORWARD</dispatcher> | |
<dispatcher>REQUEST</dispatcher> | |
<dispatcher>INCLUDE</dispatcher> | |
</filter-mapping> | |
<filter-mapping> | |
<filter-name>adfBindings</filter-name> | |
<url-pattern>*.jspx</url-pattern> | |
<dispatcher>FORWARD</dispatcher> | |
<dispatcher>REQUEST</dispatcher> | |
<dispatcher>INCLUDE</dispatcher> | |
</filter-mapping> | |
<filter-mapping> | |
<filter-name>adfBindings</filter-name> | |
<url-pattern>*.jsf</url-pattern> | |
<dispatcher>FORWARD</dispatcher> | |
<dispatcher>REQUEST</dispatcher> | |
<dispatcher>INCLUDE</dispatcher> | |
</filter-mapping> |
Step13:
In AppModule update jbo.ampool.sessioncookiefactoryclass in AppModuleLocal and AppModuleShare to point to DynamicJDBCSessionCookieFactory
Step14:
Now run login.jspx and login with database username/password = hr/hr you will successfully login and get the data
Logout then login again with wrong password as hr/hr1 you will get "Invalid username/password".
You can download the sample application from here