Thursday, November 28, 2013
Tuesday, October 22, 2013
Uploading Large Files from ADF 11g Applications
In ADF upload component if we want to increase upload file size we have to keep below code in web.xml.
<context-param>
<param-name>org.apache.myfaces.trinidad.UPLOAD_MAX_DISK_SPACE</param-name>
<param-value>20971520</param-value>
</context-param>
if we set adf instead of apache that use to throw "The file could not be uploaded because it is too large" error on upload component.
<context-param>
<param-name>org.apache.myfaces.trinidad.UPLOAD_MAX_DISK_SPACE</param-name>
<param-value>20971520</param-value>
</context-param>
if we set adf instead of apache that use to throw "The file could not be uploaded because it is too large" error on upload component.
Monday, October 14, 2013
Disable or Enable Button/InputText in ADF by using Javascript
Disabling ADF Faces UI component on the client-side could be tricky sometimes.You basically need to set unsecure="disabled" and clientComponent="true". But if you use button.setProperty('disabled', true)
on a commandButton, your button will still look like undisabled (though
it won't invoke action event), proper style class and 'disabled'
attribute will not be applied to the button element.
To properly disable button you can use script like this:
<?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:af="http://xmlns.oracle.com/adf/faces/rich">
<jsp:directive.page contentType="text/html;charset=UTF-8"/>
<f:view>
<af:document id="d1">
<af:resource type="javascript">
function disableField(actionEvent) {
var nameInputText = actionEvent.getSource().findComponent("nameFld");
nameInputText.setProperty("disabled", true);
//The following line is for partial refresh, in this case
//its taken care by framework
//AdfPage.PAGE.addPartialTargets(nameInputText);
}
function enableField(actionEvent) {
var nameInputText = actionEvent.getSource().findComponent("nameFld");
nameInputText.setProperty("disabled", false);
}
function setButtonDisabled(actionEvent) {
var button = actionEvent.getSource().findComponent("submitButton");
button.setProperty('disabled', true);
AdfDomUtils.addOrRemoveCSSClassName(true,
AdfRichUIPeer.getDomElementForComponent(button),
AdfRichUIPeer.DISABLED_STYLECLASS);
var buttonDom = button.getPeer().getButtonElement(button);
buttonDom.setAttribute('disabled', 'disabled');
}
function setButtonEnabled(actionEvent) {
var button = actionEvent.getSource().findComponent("submitButton");
button.setProperty('disabled', false);
AdfDomUtils.addOrRemoveCSSClassName(false,
AdfRichUIPeer.getDomElementForComponent(button),
AdfRichUIPeer.DISABLED_STYLECLASS);
var buttonDom = button.getPeer().getButtonElement(button);
buttonDom.removeAttribute('disabled');
}
</af:resource>
<af:form id="f1">
<af:panelGroupLayout id="pgl1">
<af:commandButton text="Disable Name Field" id="disableBtn" clientComponent="true" unsecure="disabled"
>
<af:clientListener type="action" method="setButtonDisabled"/>
</af:commandButton>
<af:commandButton text="Enable Name Field" id="enableBtn" clientComponent="true" unsecure="disabled"
>
<af:clientListener type="action" method="setButtonEnabled"/>
</af:commandButton>
<af:inputText unsecure="disabled" clientComponent="true" label="Name" id="nameFld"/>
<af:commandButton disabled="true" text="Submit" id="submitButton" clientComponent="true" unsecure="disabled">
</af:commandButton>
</af:panelGroupLayout>
</af:form>
</af:document>
</f:view>
</jsp:root>
unsecure:
A whitespace separated list of attributes whose values ordinarily can be set only on the server, but need to be settable on the client. Currently, this is supported only for the "disabled" attribute. Note that when you are able to set a property on the client, you will be allowed to by using the the .setProperty('attribute', newValue) method, but not the .setXXXAttribute(newValue) method. For example, if you have unsecure="disabled", then on the client you can use the method .setProperty('disabled', false), while the method .setDisabled(false) will not work and will provide a javascript error that setDisabled is not a function.
clientComponent:
whether a client-side component will be generated. A component may be generated whether or not this flag is set, but if client Javascript requires the component object, this must be set to true to guarantee the component's presence. Client component objects that are generated today by default may not be present in the future; setting this flag is the only way to guarantee a component's presence, and clients cannot rely on implicit behavior. However, there is a performance cost to setting this flag, so clients should avoid turning on client components unless absolutely necessary.
To properly disable button you can use script like this:
<?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:af="http://xmlns.oracle.com/adf/faces/rich">
<jsp:directive.page contentType="text/html;charset=UTF-8"/>
<f:view>
<af:document id="d1">
<af:resource type="javascript">
function disableField(actionEvent) {
var nameInputText = actionEvent.getSource().findComponent("nameFld");
nameInputText.setProperty("disabled", true);
//The following line is for partial refresh, in this case
//its taken care by framework
//AdfPage.PAGE.addPartialTargets(nameInputText);
}
function enableField(actionEvent) {
var nameInputText = actionEvent.getSource().findComponent("nameFld");
nameInputText.setProperty("disabled", false);
}
function setButtonDisabled(actionEvent) {
var button = actionEvent.getSource().findComponent("submitButton");
button.setProperty('disabled', true);
AdfDomUtils.addOrRemoveCSSClassName(true,
AdfRichUIPeer.getDomElementForComponent(button),
AdfRichUIPeer.DISABLED_STYLECLASS);
var buttonDom = button.getPeer().getButtonElement(button);
buttonDom.setAttribute('disabled', 'disabled');
}
function setButtonEnabled(actionEvent) {
var button = actionEvent.getSource().findComponent("submitButton");
button.setProperty('disabled', false);
AdfDomUtils.addOrRemoveCSSClassName(false,
AdfRichUIPeer.getDomElementForComponent(button),
AdfRichUIPeer.DISABLED_STYLECLASS);
var buttonDom = button.getPeer().getButtonElement(button);
buttonDom.removeAttribute('disabled');
}
</af:resource>
<af:form id="f1">
<af:panelGroupLayout id="pgl1">
<af:commandButton text="Disable Name Field" id="disableBtn" clientComponent="true" unsecure="disabled"
>
<af:clientListener type="action" method="setButtonDisabled"/>
</af:commandButton>
<af:commandButton text="Enable Name Field" id="enableBtn" clientComponent="true" unsecure="disabled"
>
<af:clientListener type="action" method="setButtonEnabled"/>
</af:commandButton>
<af:inputText unsecure="disabled" clientComponent="true" label="Name" id="nameFld"/>
<af:commandButton disabled="true" text="Submit" id="submitButton" clientComponent="true" unsecure="disabled">
</af:commandButton>
</af:panelGroupLayout>
</af:form>
</af:document>
</f:view>
</jsp:root>
unsecure:
A whitespace separated list of attributes whose values ordinarily can be set only on the server, but need to be settable on the client. Currently, this is supported only for the "disabled" attribute. Note that when you are able to set a property on the client, you will be allowed to by using the the .setProperty('attribute', newValue) method, but not the .setXXXAttribute(newValue) method. For example, if you have unsecure="disabled", then on the client you can use the method .setProperty('disabled', false), while the method .setDisabled(false) will not work and will provide a javascript error that setDisabled is not a function.
clientComponent:
whether a client-side component will be generated. A component may be generated whether or not this flag is set, but if client Javascript requires the component object, this must be set to true to guarantee the component's presence. Client component objects that are generated today by default may not be present in the future; setting this flag is the only way to guarantee a component's presence, and clients cannot rely on implicit behavior. However, there is a performance cost to setting this flag, so clients should avoid turning on client components unless absolutely necessary.
Friday, October 11, 2013
Reading Weather data from xml
Reading Weather data from xml
try {
String url = "http://weather.yahooapis.com/forecastrss?w=2442047&u=f";
System.out.println("::::Weather URL::::"+url);
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
DefaultHandler handler = new DefaultHandler() {
boolean flag;
public void startElement(String uri, String localName,
String qName,
org.xml.sax.Attributes attributes) throws SAXException {
try {
// _logger.info("Start Element :" + qName);
if (qName.equalsIgnoreCase("latitude")) {
flag=true;
}
if (qName.equalsIgnoreCase("description")) {
System.out.println(":::::::Start::::::Weather Condition:::::::::");
flag=true;
}
if (qName.equalsIgnoreCase("yweather:condition")) {
System.out.println(":::::::Start::::::Weather Condition:::::::::");
System.out.println(":::text:"+attributes.getValue("text"));
System.out.println(":::temp:"+attributes.getValue("temp"));
System.out.println(":::date:"+attributes.getValue("date"));
System.out.println(":::::::End::::::Weather Condition:::::::::");
}
if (qName.equals("yweather:forecast")) {
System.out.println(":::::::Start::::::Weather Forecast:::::::::");
System.out.println("Code:" + attributes.getValue("day"));
System.out.println(":::date:"+attributes.getValue("date"));
System.out.println(":::low:"+attributes.getValue("low"));
System.out.println(":::high:"+attributes.getValue("high"));
System.out.println(":::text:"+attributes.getValue("text"));
System.out.println(":::::::End::::::Weather Forecast:::::::::");
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("::::::END Processes::::::;:::");
}
// public void endElement(String uri, String localName,
// String qName) throws SAXException {
// }
public void characters(char[] ch, int start,
int length) throws SAXException {
if(flag){
String s=new String(ch, start, length);
System.out.println(":::new String(ch, start, length):::"+s.split("<br />")[0]);
flag=false;
}
}
};
System.out.println("::::::::::::::::::::::::::::::::::::::::::::");
saxParser.parse(url, handler);
System.out.println(":::::::::::::::::::::::::::");
} catch (Exception e) {
e.printStackTrace();
}
Adding Images to jspx page
<f:verbatim>
<input type="image"
src="http://l.yimg.com/a/i/us/we/52/33.gif"/>
</f:verbatim>
<af:image source="http://l.yimg.com/a/i/us/we/52/26.gif" id="i1"/>
<![CDATA[
<img src="http://l.yimg.com/a/i/us/we/52/33.gif"/>]]>
</af:group>
Thursday, October 10, 2013
Setting Multiple Java Options or Time Zone in Jdeveloper
1) We can set multiple java options in Jdeveloper
I. Goto the Project properties of Model or ViewController
II.Go to Run/Debug/Profile on the Left Pane.
III.If you are using Project Settings Click on Edit by selecting your Profile most of the cases it is
Default.
IV.Select Launch Settings on the left pane and in Java option enter this value Note: you can
change according to your options by giving space between multiple java parameters .
-Duser.timezone="+05:30" -Doracle.adfm.usemds=true
2) Error :oracle.jbo.JboException: JBO-29000: Unexpected exception caught:
java.sql.SQLDataException, msg=ORA-01882: timezone region not found
Solution : Set time zone in java options -Duser.timezone="+05:30"
This time zone is for India, you can set which ever time zone required.
I. Goto the Project properties of Model or ViewController
II.Go to Run/Debug/Profile on the Left Pane.
III.If you are using Project Settings Click on Edit by selecting your Profile most of the cases it is
Default.
IV.Select Launch Settings on the left pane and in Java option enter this value Note: you can
change according to your options by giving space between multiple java parameters .
-Duser.timezone="+05:30" -Doracle.adfm.usemds=true
2) Error :oracle.jbo.JboException: JBO-29000: Unexpected exception caught:
java.sql.SQLDataException, msg=ORA-01882: timezone region not found
Solution : Set time zone in java options -Duser.timezone="+05:30"
This time zone is for India, you can set which ever time zone required.
Tuesday, September 24, 2013
Sunday, September 8, 2013
Page Definition Variables to Store Temporary Page Values
Back to the basics. In most of the cases data is coming from Model
layer, from ADF BC or EJB. When user is changing data on the screen,
frameworks takes care and preserves temporary data. However, what about
such screens where we have temporary fields, without any relation with
the Model layer - transient data fields. What if there is no
corresponding Model implementation, and still we need to store field
data between requests - where should we store it? I believer, one of the
best techniques is to use Page Definition variables, this is old
approach back from ADF 10g times - but it still works very well. Main
advantage - we are able to store transient temporary data between
requests and there is no need to define session scope bean.
It happened to see scary things - developers are defining managed beans in Page Flow Scope, just because they want to make sure temporary UI values are preserved between requests :)
This sample implements two input components - inputText and inputNumberSlider. Both components are enabled with autoSubmit, as well as value change listener is defined for both. Once value is changed for one of the components, we recalculate total sum of both fields and display as total:
Both input components exist only in UI, there is no Model layer representation - user types values, total is recalculated immediately. However, we still need to store entered values, otherwise once we select number slider - partial request will be invoked and value entered for income will be lost. ADF developer would try to store input value inside Backing Bean:
It would be wrong to store temporary value inside Backing Bean - this bean lifetime is as long as request, in other words - once we will enter second input value, first will be always lost. You may think to define Session or even Page Flow Scope bean - that would make it work, but why to waste server memory - only if you want to make your ADF applications slow.
We can use Page Definition variables to store temporary values, these values will be preserved between requests. Open Page Definition, associated with the page, expand executables and select to insert new variable:
Give a name and specify a type for new variable:
In my example, I will define all three variables in the same way - for each of the fields:
Once variables are defined, we are not done yet with Page Definition.
For every defined variable we need to define corresponding attribute
(will be accessed from the page). Insert new item under bindings - Attribute Value:
When creating new Attribute Value, make sure to select variables as Data Source and map related variable (defined one step above) name:
Once all done, we should have following picture - each variable is assigned with attribute value:
Go back to UI now, input component should have its value property mapped with attribute value (not with variable directly, because data will not be stored/retrieved) from Page Definition. For example: bindings.incomeVarAttr.inputValue:
Once again - UI component value you should map with attribute value, not with variable directly:
Finally, you may ask question - how to access attribute values defined in Page Definition programmatically? Easy - use ADFUtils wrapper class. There are two methods available for your convenience - getBoundAttributeValue("name") and setBoundAttributeValue("name", value):
Its how it looks on UI:
This is HA compatible, In cluster this will work fine.
It happened to see scary things - developers are defining managed beans in Page Flow Scope, just because they want to make sure temporary UI values are preserved between requests :)
This sample implements two input components - inputText and inputNumberSlider. Both components are enabled with autoSubmit, as well as value change listener is defined for both. Once value is changed for one of the components, we recalculate total sum of both fields and display as total:
Both input components exist only in UI, there is no Model layer representation - user types values, total is recalculated immediately. However, we still need to store entered values, otherwise once we select number slider - partial request will be invoked and value entered for income will be lost. ADF developer would try to store input value inside Backing Bean:
It would be wrong to store temporary value inside Backing Bean - this bean lifetime is as long as request, in other words - once we will enter second input value, first will be always lost. You may think to define Session or even Page Flow Scope bean - that would make it work, but why to waste server memory - only if you want to make your ADF applications slow.
We can use Page Definition variables to store temporary values, these values will be preserved between requests. Open Page Definition, associated with the page, expand executables and select to insert new variable:
Give a name and specify a type for new variable:
In my example, I will define all three variables in the same way - for each of the fields:
When creating new Attribute Value, make sure to select variables as Data Source and map related variable (defined one step above) name:
Once all done, we should have following picture - each variable is assigned with attribute value:
Go back to UI now, input component should have its value property mapped with attribute value (not with variable directly, because data will not be stored/retrieved) from Page Definition. For example: bindings.incomeVarAttr.inputValue:
Once again - UI component value you should map with attribute value, not with variable directly:
Finally, you may ask question - how to access attribute values defined in Page Definition programmatically? Easy - use ADFUtils wrapper class. There are two methods available for your convenience - getBoundAttributeValue("name") and setBoundAttributeValue("name", value):
Its how it looks on UI:
This is HA compatible, In cluster this will work fine.
Thursday, September 5, 2013
ADF Mobile Links
ADF mobile app Usage:
http://docs.oracle.com/cd/E35521_01/doc.111230/e24475/app_usage.htm
ADF Mobile AMX User Interface:
http://docs.oracle.com/cd/E35521_01/doc.111230/e24475/amxui.htm
Developer Guide: 11.1.2.4.0
http://docs.oracle.com/cd/E37975_01/doc.111240/e24475/whatsnew_adfmf.htm#sthref8
Mobile Architecture:
http://www.oracle.com/ocom/groups/public/@otn/documents/webcontent/513078.pdf
http://docs.oracle.com/cd/E35521_01/doc.111230/e24475/app_usage.htm
ADF Mobile AMX User Interface:
http://docs.oracle.com/cd/E35521_01/doc.111230/e24475/amxui.htm
Developer Guide: 11.1.2.4.0
http://docs.oracle.com/cd/E37975_01/doc.111240/e24475/whatsnew_adfmf.htm#sthref8
Mobile Architecture:
http://www.oracle.com/ocom/groups/public/@otn/documents/webcontent/513078.pdf
Sequence number generation in EO
To generate Primary key sequence generation in EO , Best practice is generate Data Manipulation Methods and in that we have to check condition if DML_INSERT?
If we call createInsert in Updataable VO and while commit time it will call doDML() method,
While insertion time if you want Primary key generation then we need to keep condition
if(operration==this.DML_INSERT)
and we have to set sequence number to primary key column (EmployeeId).
If we call createInsert in Updataable VO and while commit time it will call doDML() method,
While insertion time if you want Primary key generation then we need to keep condition
if(operration==this.DML_INSERT)
and we have to set sequence number to primary key column (EmployeeId).
Tuesday, September 3, 2013
Monday, September 2, 2013
Disabling connection for Non DB projects
In bc4j.xml file under AppModuleConfig tag we have to put
<Custom RequiresConnection="false"/> tag.
So that when ever we creates AM or VO Jdeveloper will not ask connection, And while running also it will not give error like "java:comp/env/jdbc/hrDS" or Connection1 not available errors.
Auto calling and e-Mailing in ADF Mobile App
In ADF mobile if you want to implement email functionality ,you have to use below code.
With this code when you click on this link ,this will automatically will ask you to send with which email domain you want to send.
<amx:goLink url="mailto:sreedhar.reddy@3disystems.com"></amx:goLink>
You Can keep Subject , CC , BCC and Body also configurable.
With this code when you click on this link ,this will automatically will ask you to send with which email domain you want to send.
<amx:goLink url="mailto:sreedhar.reddy@3disystems.com"></amx:goLink>
You Can keep Subject , CC , BCC and Body also configurable.
<tr:goLink styleClass="messageText"
text="#{sessionScope.empDetails.Email}"
destination="mailto:#{sessionScope.empDetails.Email}?subject=howdy&cc=myboss@oracl
e.com&bcc=me@oracle.com&body=howdy partner!"/>
If you want to auto calling functionality in ADF mobile ,use below code.
<tr:goLink text="3256897589" destination="tel:3256897589/>If you want to auto calling functionality in ADF mobile ,use below code.
Sunday, September 1, 2013
Friday, August 30, 2013
Wednesday, August 28, 2013
Speed up ADF Mobile Deployment to Android with Keystore and "Release" Packaging
As you might have noticed from my latest ADF Mobile entries, I'm
doing most of my ADF Mobile development on a windows machine and testing
on an Android device. Unfortunately the Android/windows experience is
not as fast as the iOS/Mac one.
However, there is one thing I learned today that can make this a bit less painful in terms of the speed to deploy and test your application - and this is to use the "Release" mode when deploying your application instead of the "Debug" mode.
To do this you'll first need to define a keystore, but as Joe from our Mobile team showed me today, this is quite easy.
Here are the steps:
Open a command line in your JDK bin directory (I just used the JDK that comes with the JDeveloper install).
Issue the following command:
keytool –genkey –v –keystore <Keystore Name>.keystore –alias <Alias Name> -keyalg RSA –keysize 2048 –validity 10000
Both keystore name and alias names are strings that you decide on.
The keytool utility will then prompt you with various questions that you'll need to answer.
Once this is done, the next step is to configure your JDeveloper preferences->ADF Mobile to add this keystore there under the release tab:
Then for your application specific deployment profile - switch the build mode from debug to release.
The end result is a much smaller mobile application (for example from 60 to 21mb) and a much faster deployment cycle (for me it is about twice as fast as before).
For even faster deployment on Android - deploy to a device instead of the emulator.
As for size of the apk file there is a minimum size of 9mb that is needed for the JVM. Frankly I don't think this is an issue for people on the store - angry birds is bigger than this and they didn't have any problems getting millions of users to download their application.
However, there is one thing I learned today that can make this a bit less painful in terms of the speed to deploy and test your application - and this is to use the "Release" mode when deploying your application instead of the "Debug" mode.
To do this you'll first need to define a keystore, but as Joe from our Mobile team showed me today, this is quite easy.
Here are the steps:
Open a command line in your JDK bin directory (I just used the JDK that comes with the JDeveloper install).
Issue the following command:
keytool –genkey –v –keystore <Keystore Name>.keystore –alias <Alias Name> -keyalg RSA –keysize 2048 –validity 10000
Both keystore name and alias names are strings that you decide on.
The keytool utility will then prompt you with various questions that you'll need to answer.
Once this is done, the next step is to configure your JDeveloper preferences->ADF Mobile to add this keystore there under the release tab:
Then for your application specific deployment profile - switch the build mode from debug to release.
The end result is a much smaller mobile application (for example from 60 to 21mb) and a much faster deployment cycle (for me it is about twice as fast as before).
For even faster deployment on Android - deploy to a device instead of the emulator.
As for size of the apk file there is a minimum size of 9mb that is needed for the JVM. Frankly I don't think this is an issue for people on the store - angry birds is bigger than this and they didn't have any problems getting millions of users to download their application.
Failed to fetch URL https://dl-ssl.google.com/android/repository/repository-7.xml, reason: SSLPeerUnverified peer not authenticated
Try using "http" instead of "https". Go to the
try to clearing or unchecking the Manifest Cache in the options menu.
Android SDK Manager -> Tools -> Options...
and check "Force https://... sources to be fetched using http://..."
.try to clearing or unchecking the Manifest Cache in the options menu.
ADF Mobile: SQLite in ADF Mobile
If you want to save data
locally (in ADF Mobile), SQLite is the way to go. SQLite is a
lightweight, portable and ACID-compliant relational database management
system.
There are 2 ways of getting it (the database) in your application, by using a .sql script or by creating the .db itself and adding it to your application. I will show you the .sql way.
One of the most important things to remember is that at any given time, a single instance of the SQLite database may have either a single read-write connection or multiple read-only connections.
Although SQLite complies with the SQL92 standard, there are some restrictions but I refer you to the link below for more info about that and other subjects.
Read more about SQLite in ADF Mobile here : http://docs.oracle.com/cd/E35521_01/doc.111230/e24475/amxdatabase.htm#CIAEIGEJ
yourApplicationName/.adf/META-INF/your_script_here
In your JDev, you will see it in the Application Resources > Descriptors > ADF META-INF (you may need to refresh) (this is an example: click).
2) When you create an 'ADF Mobile Application' in your JDeveloper, you will find the LifeCycleListenerImpl.java in your ApplicationController project (it is generated by default). We will use this class to create the DB (if needed) by reading the .sql script we provided. Note that the database name = the script name!
Also don't forget to register this class to your application (because somehow this isn't done by default). This can be done by opening adfmf-application.xml (Situated in Application Resources > Descriptors >ADF META INF > here) and add the class in 'Lifecycle Even Listener' like in the picture below:
Add this to the start() method. It checks if the database already exist, if not it will call a method which will create it.
The method below is a custom method. It reads the .sql script and executes it.
3) Now that our database is/will be created, we need to handle the connection. You can find the source code below. It provides a method to retrieve the Connection and a method to close the connection.
4) Now we want to do operations on our database. I would suggest to create a database controller class, which controls all operations on your local database. The code below is just an example which isn't hard to understand.
Use this to secure your db (you should do this in the LifeCycleListenerImpl)
And this for using the connection (this should be changed in the DBConnectionFactory)
But keep in the mind the following! (quotes from the dev guide)
There are 2 ways of getting it (the database) in your application, by using a .sql script or by creating the .db itself and adding it to your application. I will show you the .sql way.
One of the most important things to remember is that at any given time, a single instance of the SQLite database may have either a single read-write connection or multiple read-only connections.
Although SQLite complies with the SQL92 standard, there are some restrictions but I refer you to the link below for more info about that and other subjects.
Read more about SQLite in ADF Mobile here : http://docs.oracle.com/cd/E35521_01/doc.111230/e24475/amxdatabase.htm#CIAEIGEJ
Practical part
Use case
I will show you a couple of things in this post.- Create a .db by using a .sql script (when your application starts).
- How to manage the connection of your SQLite DB.
- Security regarding the .db
- Doing operations on your DB (SELECT, INSERT, DELETE and UPDATE)
Let's start!
1) Before we start, we will need an .sql script. Once you obtained/created one, place it in the following folder:yourApplicationName/.adf/META-INF/your_script_here
In your JDev, you will see it in the Application Resources > Descriptors > ADF META-INF (you may need to refresh) (this is an example: click).
2) When you create an 'ADF Mobile Application' in your JDeveloper, you will find the LifeCycleListenerImpl.java in your ApplicationController project (it is generated by default). We will use this class to create the DB (if needed) by reading the .sql script we provided. Note that the database name = the script name!
Also don't forget to register this class to your application (because somehow this isn't done by default). This can be done by opening adfmf-application.xml (Situated in Application Resources > Descriptors >ADF META INF > here) and add the class in 'Lifecycle Even Listener' like in the picture below:
Add this to the start() method. It checks if the database already exist, if not it will call a method which will create it.
String databaseName = "F1_DB";
File dbFile = new File(AdfmfJavaUtilities.getDirectoryPathRoot(AdfmfJavaUtilities.ApplicationDirectory)+"/"+databaseName+".db");
if(!dbFile.exists())
{
try {
this.initializeDatabase(databaseName);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
The method below is a custom method. It reads the .sql script and executes it.
private static void initializeDatabase(String databaseName) throws Exception
{
List stmts = null;
try {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
InputStream is = cl.getResourceAsStream(".adf/META-INF/"+databaseName+".sql");
if (is == null) {
// .sql script not found
}
BufferedReader bReader = new BufferedReader(new InputStreamReader(is));
stmts = new ArrayList();
String strstmt = "";
String ln = bReader.readLine();
while (ln != null) {
if (ln.startsWith("REM") || ln.startsWith("COMMIT")) {
ln = bReader.readLine();
continue;
}
strstmt = strstmt + ln;
if (strstmt.endsWith(";")) {
System.out.println(strstmt);
stmts.add(strstmt);
strstmt = "";
ln = bReader.readLine();
continue;
}
ln = bReader.readLine();
}
String Dir = AdfmfJavaUtilities.getDirectoryPathRoot(AdfmfJavaUtilities.ApplicationDirectory);
String connStr = "jdbc:sqlite:" + Dir + "/"+databaseName+".db";
Connection conn = null;
conn = new SQLite.JDBCDataSource(connStr).getConnection();
conn.setAutoCommit(false);
for (int i = 0; i < stmts.size(); i++)
{
Statement pStmt = conn.createStatement();
pStmt.executeUpdate((String)stmts.get(i));
}
conn.commit();
conn.close();
} catch (Exception ex)
{
ex.printStackTrace();
}
}
3) Now that our database is/will be created, we need to handle the connection. You can find the source code below. It provides a method to retrieve the Connection and a method to close the connection.
public class DBConnectionFactory {
public DBConnectionFactory() {
super();
}
protected static Connection conn = null;
protected static String DBname = "F1_DB";
public static Connection getConnection() throws Exception
{
if (conn == null) {
try {
String Dir = AdfmfJavaUtilities.getDirectoryPathRoot(AdfmfJavaUtilities.ApplicationDirectory);
String connStr = "jdbc:sqlite:" + Dir + "/"+DBname+".db";
conn = new SQLite.JDBCDataSource(connStr).getConnection();
} catch (SQLException e) {
System.err.println(e.getMessage());
}
}
return conn;
}
public static void closeConnection()
{
if(conn !=null)
{
try {
conn.close();
} catch (SQLException e) {
System.err.println(e.getMessage()); }
}
conn = null;
}
}
4) Now we want to do operations on our database. I would suggest to create a database controller class, which controls all operations on your local database. The code below is just an example which isn't hard to understand.
package be.cookie.viewcontroller.controller;
public class DBController {
private static DBController db;
public DBController() {
super();
}
public static DBController getInstance()
{
if(db == null)
db = new DBController();
return db;
}
public List getDrivers()
{
List items = new ArrayList();
ResultSet result = this.queryLocalDB("SELECT * FROM DRIVER");
try {
while (result.next())
{
String first = result.getString("firstname");
String last = result.getString("lastname");
String img = result.getString("imgURI");
String nat = result.getString("nat");
String team = result.getString("team");
int wc = result.getInt("wc");
int gp = result.getInt("gp");
int gpwon = result.getInt("gpwon");
items.add(new Driver(first,last,img,nat,team,wc,gp,gpwon));
}
}
catch (SQLException e)
{
e.printStackTrace();
}
return items;
}
public List getCalendarItems()
{
List items = new ArrayList();
ResultSet result = this.queryLocalDB("SELECT * FROM CALENDAR");
try {
while (result.next())
{
int code = result.getInt("nbr");
String place = result.getString("place");
String date = result.getString("date");
String flagURI = result.getString("flagURI");
items.add(new CalendarItem(code,place,date,flagURI));
}
}
catch (SQLException e)
{
e.printStackTrace();
}
return items;
}
public String insertDrivers(List list)
{
for(int i = 0; i < list.size(); i++)
{
Driver x = (Driver)list.get(i);
PreparedStatement pStmt;
try
{
pStmt = DBConnectionFactory.getConnection().prepareStatement("INSERT INTO DRIVER VALUES(?,?,?,?,?,?,?,?,?);");
pStmt.setString(1, x.getFirstname());
pStmt.setString(2, x.getLastname());
pStmt.setString(3, x.getImgURI());
pStmt.setString(4, x.getNat());
pStmt.setString(5, x.getTeam());
pStmt.setString(6, x.getDriverURI());
pStmt.setInt(7, x.getWc());
pStmt.setInt(8, x.getGp());
pStmt.setInt(9, x.getGpwon());
pStmt.executeUpdate();
if(pStmt != null)
pStmt.close();
}
catch (Exception e)
{
return e.getMessage();
}
}
try
{
DBConnectionFactory.getConnection().commit();
}
catch (Exception e)
{
return e.getMessage();
}
return "";
}
public String deleteDriver(String firstname)
{
PreparedStatement pStmt;
try
{
pStmt = DBConnectionFactory.getConnection().prepareStatement("DELETE FROM DRIVER WHERE firstname = ? ;");
pStmt.setString(1, firstname);
pStmt.executeUpdate();
if(pStmt != null)
pStmt.close();
}
catch (Exception e)
{
return e.getMessage();
}
return "";
}
public String updateDriver(String firstname, Driver x)
{
PreparedStatement pStmt;
try
{
pStmt = DBConnectionFactory.getConnection().prepareStatement("UPDATE DRIVER SET team = ?, wc = ?, gp = ?, gpwon = ? WHERE firstname = ? ;");
pStmt.setString(1, x.getTeam());
pStmt.setInt(2, x.getWc());
pStmt.setInt(3, x.getGp());
pStmt.setInt(4, x.getGpwon());
pStmt.setString(5, firstname);
}
catch (Exception e)
{
return e.getMessage();
}
return "";
}
/**
* @param query
* @return ResultSet queryResult
*/
private ResultSet queryLocalDB(String qry)
{
Statement stat = null;
ResultSet result = null;
try
{
stat = DBConnectionFactory.getConnection().createStatement();
result = stat.executeQuery(qry);
if(result.equals(null))
{
return null;
}
else
return result;
}
catch(Exception ex)
{
return null;
}
}
}
Security
When running the code provided in this blog, people can just locate the .db file and read it by using some program (I use SQLite database browser for Mac). Ideal for debugging but not for production. Securing the .db file can be done in few lines of code!Use this to secure your db (you should do this in the LifeCycleListenerImpl)
AdfmfJavaUtilities.encryptDatabase(conn, "mypassword");
And this for using the connection (this should be changed in the DBConnectionFactory)
OLD: conn = new SQLite.JDBCDataSource(connStr).getConnection(); NEW: conn = new SQLite.JDBCDataSource(
connStr)
).getConnection(null,"mypassword");
But keep in the mind the following! (quotes from the dev guide)
In the preceding example, the first parameter of the getConnection method is the user name, but since SQLite does not support user-based security, this value is ignored.
Note: SQLite does not display any error messages if you open an encrypted database with an incorrect password. Likewise, you are not alerted if you mistakenly open an unencrypted database with a password. Instead, when you attempt to read or modify the data, an SQLException is thrown with the message "Error: file is encrypted or is not a database".
Caution: If you open a database incorrectly (for example, use an invalid password to open an encrypted database), and then encrypt it again, neither the old correct password, the invalid password, nor the new password can unlock the database resulting in the irretrievable loss of data.
Tuesday, August 27, 2013
Book Mark Share
function Twitter_Share() {
var TwitterTitle
try{
TwitterTitle = document.getElementById("EventName").innerHTML;
}catch (e){
TwitterTitle = document.title;
}
if (TwitterTitle == "" || TwitterTitle == null) {
TwitterTitle = document.title;
}
TwitterTitle = html_entity_decode(TwitterTitle)
TwitterTitle = encodeURIComponent(TwitterTitle)
var ShareURL = "https://twitter.com/intent/tweet?text=" + TwitterTitle + "&url=" + ShareTrackingUrl;
window.open(ShareURL, '_blank', 'width=750, height=400')
}
function Weibo_Share() {
var WeiboTitle;
try{
WeiboTitle = document.getElementById("EventName").innerHTML;
}catch (e){
WeiboTitle = document.title;
}
if (WeiboTitle == "" || WeiboTitle == null) {
WeiboTitle = document.title;
}
WeiboTitle = html_entity_decode(WeiboTitle)
WeiboTitle = encodeURIComponent(WeiboTitle)
var ShareURL = "http://service.weibo.com/share/share.php?url=" + ShareTrackingUrl +"&title=" + WeiboTitle;
window.open(ShareURL, '_blank', 'width=750, height=400')
}
function FB_Share() {
getTrackUrl()
var FBTitle;
var FBDescription;
try{
FBTitle = document.getElementById("EventName").innerHTML;
}
catch (e){
FBTitle = document.title;
}
if (FBTitle == "" || FBTitle == null) {
FBTitle = document.title;
}
try{
FBDescription = $('meta[name=Description]').attr("content");
}catch (e){
FBDescription = "";
}
if (FBDescription == "" || FBDescription == null) {
FBDescription = "";
}
//FBDescription = "";
FBDescription = html_entity_decode(FBDescription)
FBTitle = html_entity_decode(FBTitle)
FBTitle = encodeURIComponent(FBTitle)
FBDescription = encodeURIComponent(FBDescription)
var ShareURL =
"https://www.facebook.com/sharer/sharer.php?s=100&p[title]=" +
FBTitle + "&p[summary]=" + FBDescription + "&p[url]=" +
ShareTrackingUrl +
"&p[images][0]=http://www.oracleimg.com/us/dm/fb-share-304843.jpg&"
window.open(ShareURL, '_blank', 'width=750, height=400')
}
function Linkedin_Share() {
var LinkedinTitle;
var LinkedinDescription;
try {
LinkedinTitle = document.getElementById("EventName").innerHTML;
}
catch (e) {
LinkedinTitle = document.title;
}
if (LinkedinTitle == "" || LinkedinTitle == null) {
LinkedinTitle = document.title;
}
try{
LinkedinDescription = $('meta[name=Description]').attr("content");
}
catch (e){
LinkedinDescription = "";
}
if (LinkedinDescription == "" || LinkedinDescription == null) {
LinkedinDescription = "";
}
//LinkedinDescription = "";
LinkedinDescription = html_entity_decode(LinkedinDescription)
LinkedinTitle = html_entity_decode(LinkedinTitle)
LinkedinTitle = encodeURIComponent(LinkedinTitle)
LinkedinDescription = encodeURIComponent(LinkedinDescription)
var ShareURL =
"http://www.linkedin.com/shareArticle?mini=true&url=" +
ShareTrackingUrl + "&title=" + LinkedinTitle + "&summary=" +
LinkedinDescription ;
window.open(ShareURL, '_blank', 'width=750, height=400')
}
function Mail_Share() {
var MailTitle;
try {
MailTitle = document.getElementById("EventName").innerHTML;
}
catch (e) {
MailTitle = document.title;
}
if (MailTitle == "" || MailTitle == null) {
MailTitle = document.title;
}
MailTitle = MailTitle.replace(/&/g, "%26");
mail_str = "mailto:?subject=Thought this might interest you: " + MailTitle;
mail_str += "&body=I thought you might be interested in this: " + MailTitle;
mail_str += ". %0A%0AYou can view it at, " + ShareTrackingUrl;
mail_str = mail_str.replace(/%26amp;/g, "%26");
location.href = mail_str;
}
http://eventreg.oracle.com/profile/web/index.cfm?PKWebId=0x9235b9f5
Monday, August 26, 2013
ORA-01654: unable to extend index PS6_MDS.MDS_ATTRIBUTES_U2 by 1024 in tablespace PS6_MDS
You need to add more space to your datafile/tablespace, or extend the index.
Note: 1025288.6 - How to Diagnose and Resolve UNABLE TO EXTEND Errors
https://metalink2.oracle.com/metalink/plsql/ml2_documents.showDocument?p_database_id=NOT&p_id=1025288.6
Note: 19049.1 - OERR: ORA 1654 unable to extend index by for tablespace
https://metalink2.oracle.com/metalink/plsql/ml2_documents.showDocument?p_database_id=NOT&p_id=19049.1
Note: 762273.1 - ORA-1654: unable to extend index
https://metalink2.oracle.com/metalink/plsql/ml2_documents.showDocument?p_database_id=NOT&p_id=762273.1
SQL> alter index APPLSYS.SYS_IOT_TOP_34179 storage (maxextents unlimited);
SQL> ALTER TABLESPACE <tablespace name> ADD DATAFILE '<full path and file name>' SIZE <integer> <K|M>;
Note: 1025288.6 - How to Diagnose and Resolve UNABLE TO EXTEND Errors
https://metalink2.oracle.com/metalink/plsql/ml2_documents.showDocument?p_database_id=NOT&p_id=1025288.6
Note: 19049.1 - OERR: ORA 1654 unable to extend index by for tablespace
https://metalink2.oracle.com/metalink/plsql/ml2_documents.showDocument?p_database_id=NOT&p_id=19049.1
Note: 762273.1 - ORA-1654: unable to extend index
https://metalink2.oracle.com/metalink/plsql/ml2_documents.showDocument?p_database_id=NOT&p_id=762273.1
Tuesday, August 13, 2013
Unknown character set in properties bundle
Problem : I faced some issue in Jdeveloper ,when i installed JDeveloper in Linux ,my application spanish properties bundle showing unknown character set.
Solution : JDeveloper-->Tools-->Preferences --> Environment-->Encoading -->cp1252
Solution : JDeveloper-->Tools-->Preferences --> Environment-->Encoading -->cp1252
Tuesday, August 6, 2013
WebCenter Performance Tuning Links
https://blogs.oracle.com/ATEAM_WEBCENTER/entry/improving_webcenter_performance
https://blogs.oracle.com/ATEAM_WEBCENTER/entry/improving_webcenter_performance_part_2
https://blogs.oracle.com/ATEAM_WEBCENTER/entry/monitor_performance_with_enterprise_manager
https://blogs.oracle.com/ATEAM_WEBCENTER/entry/improving_webcenter_performance_part_21
https://blogs.oracle.com/ATEAM_WEBCENTER/entry/improving_webcenter_content_search_performance
https://blogs.oracle.com/ATEAM_WEBCENTER/entry/adf_deployment_view_layer_tuning
https://blogs.oracle.com/ATEAM_WEBCENTER/entry/improving_webcenter_performance_part_2
https://blogs.oracle.com/ATEAM_WEBCENTER/entry/monitor_performance_with_enterprise_manager
https://blogs.oracle.com/ATEAM_WEBCENTER/entry/improving_webcenter_performance_part_21
https://blogs.oracle.com/ATEAM_WEBCENTER/entry/improving_webcenter_content_search_performance
https://blogs.oracle.com/ATEAM_WEBCENTER/entry/adf_deployment_view_layer_tuning
Sorting Maps
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import org.apache.poi.hssf.record.formula.functions.Weekday;
public class Aaaaaaaa {
public static void main(String args[]){
WeakHashMap hashMap=new WeakHashMap();
hashMap.put("5","Sreedhar5" );
hashMap.put("6","Sreedhar6" );
hashMap.put("2","Sreedhar2" );
hashMap.put("4","Sreedhar4" );
hashMap.put("7","Sreedhar7" );
hashMap.put("8","Sreedhar8" );
HashMap passedMap=new HashMap();
passedMap.put("5","Sreedhar5" );
passedMap.put("6","Sreedhar6" );
passedMap.put("2","Sreedhar2" );
passedMap.put("4","Sreedhar4" );
passedMap.put("7","Sreedhar7" );
passedMap=sortHashMapByValuesD(passedMap);
System.out.println(":::passedMap::::"+passedMap);
System.out.println("\n hashMap::::::"+hashMap);
System.out.println(":::::::"+sortHashMapByValues(passedMap, false));
}
public static LinkedHashMap sortHashMapByValuesD(HashMap passedMap) {
List mapKeys = new ArrayList(passedMap.keySet());
List mapValues = new ArrayList(passedMap.values());
Collections.sort(mapValues);
Collections.sort(mapKeys);
LinkedHashMap sortedMap =
new LinkedHashMap();
Iterator valueIt = mapValues.iterator();
while (valueIt.hasNext()) {
Object val = valueIt.next();
Iterator keyIt = mapKeys.iterator();
while (keyIt.hasNext()) {
Object key = keyIt.next();
String comp1 = passedMap.get(key).toString();
String comp2 = val.toString();
if (comp1.equals(comp2)){
passedMap.remove(key);
mapKeys.remove(key);
sortedMap.put((String)key, (String)val);
break;
}
}
}
return sortedMap;
}
public static LinkedHashMap sortHashMapByValues(HashMap passedMap, boolean ascending) {
//Asending and Desending
List mapKeys = new ArrayList(passedMap.keySet());
List mapValues = new ArrayList(passedMap.values());
Collections.sort(mapValues);
Collections.sort(mapKeys);
if (!ascending)
Collections.reverse(mapValues);
LinkedHashMap someMap = new LinkedHashMap();
Iterator valueIt = mapValues.iterator();
while (valueIt.hasNext()) {
Object val = valueIt.next();
Iterator keyIt = mapKeys.iterator();
while (keyIt.hasNext()) {
Object key = keyIt.next();
if (passedMap.get(key).toString().equals(val.toString())) {
passedMap.remove(key);
mapKeys.remove(key);
someMap.put(key, val);
break;
}
}
}
return someMap;
}
}
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import org.apache.poi.hssf.record.formula.functions.Weekday;
public class Aaaaaaaa {
public static void main(String args[]){
WeakHashMap hashMap=new WeakHashMap();
hashMap.put("5","Sreedhar5" );
hashMap.put("6","Sreedhar6" );
hashMap.put("2","Sreedhar2" );
hashMap.put("4","Sreedhar4" );
hashMap.put("7","Sreedhar7" );
hashMap.put("8","Sreedhar8" );
HashMap passedMap=new HashMap();
passedMap.put("5","Sreedhar5" );
passedMap.put("6","Sreedhar6" );
passedMap.put("2","Sreedhar2" );
passedMap.put("4","Sreedhar4" );
passedMap.put("7","Sreedhar7" );
passedMap=sortHashMapByValuesD(passedMap);
System.out.println(":::passedMap::::"+passedMap);
System.out.println("\n hashMap::::::"+hashMap);
System.out.println(":::::::"+sortHashMapByValues(passedMap, false));
}
public static LinkedHashMap sortHashMapByValuesD(HashMap passedMap) {
List mapKeys = new ArrayList(passedMap.keySet());
List mapValues = new ArrayList(passedMap.values());
Collections.sort(mapValues);
Collections.sort(mapKeys);
LinkedHashMap sortedMap =
new LinkedHashMap();
Iterator valueIt = mapValues.iterator();
while (valueIt.hasNext()) {
Object val = valueIt.next();
Iterator keyIt = mapKeys.iterator();
while (keyIt.hasNext()) {
Object key = keyIt.next();
String comp1 = passedMap.get(key).toString();
String comp2 = val.toString();
if (comp1.equals(comp2)){
passedMap.remove(key);
mapKeys.remove(key);
sortedMap.put((String)key, (String)val);
break;
}
}
}
return sortedMap;
}
public static LinkedHashMap sortHashMapByValues(HashMap passedMap, boolean ascending) {
//Asending and Desending
List mapKeys = new ArrayList(passedMap.keySet());
List mapValues = new ArrayList(passedMap.values());
Collections.sort(mapValues);
Collections.sort(mapKeys);
if (!ascending)
Collections.reverse(mapValues);
LinkedHashMap someMap = new LinkedHashMap();
Iterator valueIt = mapValues.iterator();
while (valueIt.hasNext()) {
Object val = valueIt.next();
Iterator keyIt = mapKeys.iterator();
while (keyIt.hasNext()) {
Object key = keyIt.next();
if (passedMap.get(key).toString().equals(val.toString())) {
passedMap.remove(key);
mapKeys.remove(key);
someMap.put(key, val);
break;
}
}
}
return someMap;
}
}
Subscribe to:
Posts (Atom)