Monday, May 1, 2017

Oracle JET: First Hybrid android Mobile App

Problem Description: In this blog I am just putting all steps those I followed to create a mobile app using Oracle JET

Solution: Here are the steps that I followed to create my first application. As there are multiple ways to start JET development so I would not say this is best way but this is what works for me.



1.      Install Node.js: https://nodejs.org/en/download. Once node is installed you should be able to run npm commands.

2.      Run command prompt in Admin mode and then run below commands to install various npm modules
a.       npm install -g cordova
b.      npm install -g yo
c.       npm install -g grunt-cli
d.      npm install -g bower
e.       npm install -g generator-oraclejet
f.       npm install -g cordova

3.      Install android sdk: I have installed android studio, which comes with android sdk as well. https://developer.android.com/studio/index.html

4.      Use SDK Manager and install api required api: To launch SDK manager from android studio you need not to create any project. You can simply start android studio and select configure option


      
                 Below image shows how my SDK manager looks like





5.   Create web project and run it.
a.       Navigate to directory where you want to create project (say: D:\practice-jet)
b.      Before creating porject verify that you have all npm modules installed:  


npm list -g --depth=0

        
       
  
                 c.    Run command: I prefer creating a web project first and then add hybrid mobile
                        application feature to it.
 yo oraclejet MyFirstApp --template=navdrawer:hybrid

 
  
                  d.     cd MyFirstApp
                  e.      grunt build

                    f.     grunt serve
                  grunt serve command will start a process at port 8000 port. Your page will be visible on
                  browser at http://localhost:8000
                    we can kill process using ctrl+c.  Now our application is running fine on browser. We
                    have following directory structure till now.
 6.     Let us add android feature to our project
         yo oraclejet:add-hybrid --platforms=android
           If we see directory structure, it has got two additional directory src-web and src-hybrid. We already have one src directory. Main (or common code ) will reside in src folder. Code which is only applicable to web application will go in src-web project. Code which is only applicable to hybrid application will be in src-hybrid folder.

   7.      Build project
          grunt build --platform=android

            This step has created an android-debug.apk file in D:\practice-jet\MyFirstApp\hybri\platforms\android\build\outputs\apk folder. 

8. Create release ready apk file
Keystore with key creation: Now we want to create a release ready apk file. For that we need to first use keytool to create keystore and alias. We can run below command for that 
keytool -genkey -v -keystore MyFirstApp.keystore -alias MyFirstApp -keyalg RSA -keysize 2048 -validity 10000
Command should ask for password for keystore and key. It will also ask for additional details like lastname, first name etc. You can hit enter if you don't want to provide. 

We can keep keystore file outside project so that you can use same keystore with multiple application. My KeyStore name is MyFirstApp, password is 'manager' and Key name is agains MyFirstApp. Keystore and key passwords are same. Definitely you will have different keystore/key/passwords.

    
Now we will create a buildconfig file, which has entry of keystore. I placed file in d:\practice-jet folder. Content of file looks like


Finally run below command to generate release ready apk file

grunt serve:release --platform=android --buildConfig=D:\practice-jet\buildConfig.json
                       
  

   I have moved file to my android phone and installed apk. Here is the image of running application


9. Edit something in code and verify changes.
     To edit code you should make changes in src folder and then use grunt serve command to run it.
     NOTE: to edit web specific code use src-web and to edit hybrid specific code use src-hybrid.
    NOTE: As we have multiple platform now grunt serve will not be enough, we need to specify  which platform. Use command grunt serve --platform=web to run its web version in browser.

To sum up, we have run following important commands



1.      One time setup
a.       Node install
b.      Node module install
                                                              i.      npm install -g cordova
                                                            ii.      npm install -g yo
                                                          iii.      npm install -g grunt-cli
                                                          iv.      npm install -g bower
                                                            v.      npm install -g generator-oraclejet
                                                          vi.      npm install -g cordova
c.       Android SDK installation

2.      Project Specific setup
a.       Create project: yo oraclejet MyFirstApp --template=navdrawer:hybrid
b.      cd MyFirstApp
c.       grunt build
d.      grunt serve
e.       Add hybrid features: yo oraclejet:add-hybrid --platforms=android
f.       grunt build --platform=android
g.      Create keystore: keytool -genkey -v -keystore MyFirstApp.keystore -alias MyFirstApp -keyalg RSA -keysize 2048 -validity 10000
h.      Create buildConfig file
i.        Create release ready apk file: grunt serve:release --platform=android --buildConfig=D:\practice-jet\buildConfig.json

From here you can use NetBeans for development: To do so, you can follow
http://sanjeev-technology.blogspot.in/2017/05/oracle-jet-hybrid-android-app-using.html

Tuesday, April 25, 2017

ADF: Popup gets closed automatically

Problem description: I found at times people complaint that ADF popup gets closed automatically.
In this blog I am trying to figure out possible cause of popup getting closed.

Possible cause: There are following four scenarios when a popup gets closed.
          1. User selects default buttons or close icon of dialog
          2. User programmatically closes popup using hide function
          3. User hit enter/escape key
          4. Popup or its parent component gets refreshed.

In first two points popup getting closed is desired behavior.

In third case when you use default buttons of popup, it gets closed with enter/escape keys. If you don't want you can use custom buttons as suggested in blog https://blogs.oracle.com/jheadstart/entry/adf_faces_how_to_prevent_closi

Point 4 is most problamatic, when user is not doing anything to close popup but it gets closed automatically. This happens when as a ppr we refresh popup or any of its parent component.
Lets take a scenario:
You have an inputText on popup the moment you enter its value and tab out your popup is getting closed. This may be because you are refreshing popup or any of its parent component. When you do so popup gets closed automatically. Your popup or any parent component of it might have partialtrigger property pointing to inputText. Or you may have valuechangeListener on inputText and you programmatically using addPartialTarget trying to refresh a component, which is having popup as child component in hierarchy.

Most of the time this happens accidentally. You decide to refresh UI component on base page and forget that same UI component is having popup also as child component. As a good practice I can suggest that we should move all our popups in single panelGroupLayout and keep them somewhere close to root components. For example

PanelGroupLayout -container
    PanelGroupLayout - main  [Keep your main page content here]
    PanelGroupLayout - popus  [Keep all your popups together here]
        af:popup1
        af:popup2

Keeping popups out of main page ensure that you can freely refresh main page components while working on popups.
One exception to this rule I see is when you have inline popups. For example you have a table and every row is showing some information in popup (may be on hover) and you have added popup inside a column with contentDelivery=immediate to make sure that popup launches quick with making a server trip. In such cases you have to add popup inside and refer #{row.myAttribute} kind of expression's EL in those.


Thats all.
  

Wednesday, April 19, 2017

Change webservice endpoint at runtime

Problem Description: In ADF we can create a webservice proxy and if we see the main class which extends Service has references of wsdl like
Now if we have dev/uat/production environment and for each environment we need to change endpoint, it could be very bad to change url manually and then generate ear. We need a way to dynamically change url at runtime.


Solutions
What we can do is keep service class as it is. We can use Client class, which we use to create instance of Servce and while creating instance we can provide url

Let say my client class is HCMUserDetailService. I change its constructor to accept url from outside.

    public HCMUserDetailService(String wsdlLocation, String username, String password) {
        super();
        userDetailsService_Service =  new UserDetailsService_Service(wsdlLocation, new QName("http://xmlns.oracle.com/apps/hcm/people/roles/userDetailsServiceV2/",
                    "UserDetailsService"));
        SecurityPoliciesFeature securityFeatures =     new SecurityPoliciesFeature(new String[] { "oracle/wss_username_token_over_ssl_client_policy" });
        userDetailService =      userDetailsService_Service.getUserDetailsServiceSoapHttpPort(securityFeatures);
        Map<String, Object> reqContext =  ((BindingProvider)userDetailService).getRequestContext();
        reqContext.put(BindingProvider.USERNAME_PROPERTY, username);
        reqContext.put(BindingProvider.PASSWORD_PROPERTY, password);
        objectFactory = new ObjectFactory();
             
       
    }



In above code constructor accepts a wsdl url as input and use that to create service instance using UserDetailsService_Service(wsdlLocation,new QName....


Now anybody needs to invoke service using this proxy we can pass wsdl location as input.

User of this client can read wsdl from
1. web.xml context parameter and then use deployment plan to change value of web.xml
2. from database table.

That way wsdl url is not hardcoded and it will get changed dyanamically.

Thats all.

Sunday, April 16, 2017

JCS/JCS-SX: Creating application server connection

Problem Description: I see most of the time people face issues while creating connection with JCS server using Jdev. Its pretty straight forward but we provide wrong details most of the time.

Solution

1. Use Resources pane and select New Connection > Application Server

2. If this JCS account then you can enable your weblogic ports 7001/7002 to public and make normal weblogic application server connection in Resource tab.


3. If its JCS-SX then you may want to use Oracle Cloud type of application-server connection. On first tab provide any name to your connection and select connection-type = Oracle Cloud


4. Next tab provide username/password. NOTE: These are cloud service user not weblogic user. In normal weblogic connection we provide weblogic user and its password but here it should be cloud user and password. If you don't have cloud user details ask cloud admin (who owns identity domain of cloud).



5. Next tab is where you need to select cloud service details [Datacenter, Identity-domain, Service Name]. This is the tab where I see mistakes most of the time. We should be knowing how to get these information. For that login to your cloud my services dashboard.

Datacenter, you always know as that is first thing you select when you want to login to your cloud account. Most of the time for me its us2.

Find identity domain on dashboard



   Select your JCS-SX instance and launch Service Detail page. 
   Get Service-Name as shown below from Service Detail page


   You can also get service name from Java console. Select Java Console from service detail page
   Service Name is mentioned at top of page


Now mention these details on your Jdev connection


Navigate to Test tab and perform a test



Thats all.