Thursday, August 12, 2010

Oracle Database XE on Linux



The Problem

On Linux, (I'm using Ubuntu 10.04 ) disabling autostart of Oracle XE at system boot prevents you from being able to start Oracle XE at all.

If you're installing Oracle XE on say, your personal laptop, hoping to do a bit of hobby like projects, you may not want to enable the DB to start up every time the system boots up. The DB after being installed has a configuration script ( /etc/init.d/oracle-xe configure ) that asks you if you want the DB to start up every time the computer boots up. If you chose not to start it automatically, you may realize that after the reboot, your DB does not seem to start, specifically the listener does not start, so you will be able to connect only through SQL*Plus. At this point, the
/etc/init.d/oracle-xe start
simply does not seem to do anything.




The Solution

Runlevel management.
Install Oracle XE with the 'start at boot time' option enabled or if you already installed with this disabled, enable it.

Enable/Disable Oracle XE database autostart

/etc/init.d/oracle-xe enable
enable autostart
/etc/init.d/oracle-xe disable
disable autostart



Once you have enabled autostart, you can use
and disable oracle-xe from run-levels 2,3,4 and 5. See below 


Thats it ! You're done. Now you can start/stop oracle any time using the following commands :

/etc/init.d/oracle-xe start
Start Oracle XE
/etc/init.d/oracle-xe stop
Strop Oracle XE

The run-levels correspond to the multiuser environment in the Ubuntu and other Debian flavored Linux distributions. Preventing the oracle-xe script from running in this manner is essentially configuring it to run at boot time, but conveniently telling the system to skip running the start up script.

The problem seems to be that Oracle XE uses a second configuration file for its startup scripts that maintain some of these settings. This file can be found in

/etc/default/oracle-xe

Within this file you see :
# ORACLE_DBENABLED:'true' means to load the Database at system boot.
ORACLE_DBENABLED=true

If this property is set to false, as it would be if you chose not to run start the DB at boot time, then the /etc/init.d/oracle-xe start does not work. The problem is possibly in the /etc/init.d/oracle-xe script, but this seemed a better solution than debugging and editing the script. Maybe I'll try editing the script one of these days...



Update : I'm told that I should not modify and redistribute the shell script, but if you dont mind getting your hands a bit dirty, take a look at the start() function in the script :
(The problem is that th listener is not started... Hmmm.. anything looking suspicious ?)
status=`ps -ef | grep tns | grep oracle`
        if [ "$status" == "" ]
        then
                if [ -f $ORACLE_HOME/bin/tnslsnr ]
                then
                        echo "Starting Oracle Net Listener."
                        $SU -s /bin/bash $ORACLE_OWNER -c "$LSNR  start" > /dev/null 2>&1
                fi
        fi


Friday, August 6, 2010

ADF Application with multiple Data Sources or Database connections

The Problem: ADF Application with multiple Data Sources or Database connections.

This is a pretty normal use-case, but can be a bit puzzling to new developers. Most apps have more than one database that they connect to. One way of dealing with this is to hide the fact there are multiple databases under the DB layer through the use of synonyms and DBlinks, but sometimes such access is not possible or desirable.  Here I discuss how to use multiple databases from ADF BC.

Solution: Multiple Root Application Modules

The basic element here is the notion of the Root Application Module. For starters, the Root Application Module defines the transactional context.  You need to create two application Modules, each one connecting to its own Database. You could also connect the very same application module to two different databases if you need to, more on that later.  Nesting one application module inside another to get access to it won’t work as nested application modules share the same root.
So the way to do this is to create a *new* _Root_ Application Module directly from the BC4J configuration. This ensures that the connection associated with that Application module’s configuration is used. The ADF model layer usually takes care of handling instances of you Application Modules, and here, you are doing it manually. This brings some risk, and be careful to release the Application Module after use.

Create Project

Start out by creating one or more model projects in your application. In most cases you’ll only require one project, but if you need to create the ADF BC objects from database tables, you will likely need two projects so you don’t have to switch connections in the same project at design time. The “Connection” you see in the Project Properties > Business Components (click on Business Components) is used only during design time to generate ADF BC objects from a DB. An Application Module’s Configuration(bc4j.xml) defines the connection it uses at run time .

Figure 1
The two model projects will house the Application Modules that connect to the two different Databases.

Configuration

Once the model projects are created, open the Configuration dialog box for the Application modules. The connection an Application Module uses at runtime is defined in the Application Module’s configuration and not the project properties.


      

The Manage Configurations dialog lists the Configurations available for that AM. The configuration for an AM encapsulates the parameters for the AM like the connection it uses. The configuration name is important as we’ll later use it to identify a particular named configuration and use that named configuration to create an Application Module instance. To specify the parameters inside the named configuration, select the configuration name, and choose Edit
  

I’m assuming that a Data Source will be used. If using a JDBC URL, the steps are the same. A valid Data Source name is defined for the first DB and the steps should be repeated the same for the second Application Module connecting to the second DB. These Data sources need to be available at runtime, so either they need to exist in the Application server you are deploying to, or you need to deploy them as part of your application.  I’m using the automatic deployment of DS provided by JDeveloper (this might not be suitable for production) so JDeveloper automatically provides a Data Source entry in this wizard based on the connections defined at the Application or IDE level. These Data sources have name that is the connection name appended with the two letters ‘DS’.   After editing the Data source, you have effectively created a Configuration called DB_One_ServiceLocal  (see screenshot) that uses the Data Source /jdbc/database_1DS  . This configuration can now be used anytime to create a root application module with the configured parameters (like an alternate Data Source ).

A note about Data Sources

See this for how to deploy a Data source manually.
This explains how to make use of JDeveloper’s automatic data source deployment.


Here is where most people get puzzled. After creating two Application Modules, you would be tempted to nest your second application module inside your first. This does not work, as the transaction context is defined for the root application module, and when you nest, the root application module does not change, and so the connection does not change. The connection used is the root Application Module’s connection. The solution is to create a new Root Application Module directly from the named BC4J configuration we created. This being a root application module on its own ensures that the connection associated with that Application module’s configuration is used. 

The Code

The following screenshot shows the classes generated by JDeveloper, nothing out of the ordinary.

The second app module exposes a method on its client interface that the first application module invokes.
Here is the method the second AM exposes on its client interface:
/**
   * Method exposed by this AM to provide the query results from its VO.
   * Since this AM's configuration connects it to the second database,
   * the VO query is executed agaist that DB
   *
   * @return
   */
   public String querySecondDB()  {
      getDBTwoVO().executeQuery();
      return ((DBTwoVORowImpl) getDBTwoVO().first()).getSampledata();
   }
   
Now in order for the first application module t access and query the second data base, it creates a new root application module instance of the second application module using the named configuration that connects it to the second database. Once the new root application module instance is obtained, the exposed method is invoked and depending on the scenario, the root application module instance is released. The method used is Configuration. createRootApplicationModule()
public String queryMulipleDBs(){
    getDBOneVO().executeQuery();
    String fromDBOne;
    String fromSecondDB;
    fromDBOne = ((DBOneVORowImpl) getDBOneVO().first()).getSampledata();
    // Create new root AppModule from the named Configuration
    DB_Two_Service service =  (DB_Two_Service)Configuration.createRootApplicationModule("sample.model2.services.DB_Two_Service", "DB_Two_ServiceLocal");
    // Query the second DB
    fromSecondDB = service.querySecondDB();
    Configuration.releaseRootApplicationModule(service,true); //releases and removes the AppModule
    return "from first DB : " + fromDBOne + " from second DB : " +fromSecondDB;

  }
   
If you have the queryMulipleDBs() method of the first Application Module exposed on its client interface, you can use the Business components test to validate the whole thing since with 11g, the Business components tester can work with Data sources as well.


A note about multiple Projects and Application Modules

Here we used a separate project and an Application Module to connect to our second DB. This however is a personal preference, I like this because it keeps the code easily readable and separates the artifacts cleanly. The real crux of the technique is an alternative root application module using a particular configuration. So ineffect you could have two ApplicationModules in the same project with thier configurations connecting to two DBs or you could have the same ApplicationModule definition with just an alternative Configuration(that connects to the other DB) and instantiate a new instance of the same ApplicationModule definition as a root AM, with the alternate Configuration using the same code. 
Configuration.createRootApplicationModule(
                                  "sample.model.services.DB_One_Service",
                                  "CONFIG_WITH_A_SECOND_DATASOURCE");
So here we have the first AM instantiating another root instance of itself with another Configuration, one that connects to another DataSource.