Friday 25 May 2007

Adding users in the jazn-data.xml file of a deployed aplication in OC4J

Poor man's authentication in applications deployed on an OC4J instance of an Oracle 10.1.3.x application server often comes down to using basic HTTP authentication and storing user names and passwords in the jazn-data.xml file located in the src/META-INF folder of your ViewController (or UserInterface) project. The technique is documented in Chapter 10 of the Oracle Application Development Framework: Tutorial 10g Release 3 (10.1.3).

A question that I had to answer the first time i started using this was how to change a user's password. I posted this to the JDeveloper forum and Frank Nimphius explained that it is as easy as entering the text in clear text preceded by an ! and then restarting the OC4J instance. The passowrd gets automatically hashed.

The other thing I found out is that, when the application gets redeployed then the jazn-data.xml file does not get copied to the application server so you are left with the initial users created during the initial deployment.

The actual file is stored in $ORACLE_HOME/j2ee/OC4J_NAME//application-deployments/myApp where OC4J_NAME is the name of the oc4j instance and MyApp is the name of the j2ee application.

The best way for me to handle this is to edit and test it on local PC, then copy it to the application server and restart OC4J. So for my EOrders application deployed in the OC4J_SAP instance the story goes like this :

oracle@lachesis:~/product/10.1.3.1/OracleAS_1/j2ee/OC4J_SAP/application-deployments/EOrders> scp thanassis@lxBakalidis:/home/thanassis/jdevhome/mywork/EOrders/View
Controller/src/META-INF/jazn-data.xml .
Password:
jazn-data.xml                                                                100% 2419     2.4KB/s   00:00
oracle@lachesis:~/product/10.1.3.1/OracleAS_1/j2ee/OC4J_SAP/application-deployments/EOrders> vi jazn-data.xml
oracle@lachesis:~/product/10.1.3.1/OracleAS_1/j2ee/OC4J_SAP/application-deployments/EOrders> opmnctl startproc  process-type=OC4J_SAP
opmnctl: starting opmn managed processes...
oracle@lachesis:~/product/10.1.3.1/OracleAS_1/j2ee/OC4J_SAP/application-deployments/EOrders>

Wednesday 23 May 2007

Oracle IAS 10g 10.1.3.x Enabling and using SSO Authentication

Reading again from the manual, enabling Single-Sign-On for deployed applications on a new 10.1.3.x application server midtier is a three step process For this example my new instance uses the DNS name lachesis.shelman.int and the HTTP server listens at port 80, while my 10.1.2 infrastructure host is named eudoxia:
  1. Create the SSO configuration file on the host running infrastructure services in my case this is a 10.1.2 Oracle IAS infrastructure.
    oracle@eudoxia:~/sso_reg> $ORACLE_HOME/sso/bin/ssoreg.sh 
               -oracle_home_path $ORACLE_HOME 
               -config_mod_osso TRUE 
               -site_name lachesis.shelman.int 
               -remote_midtier 
               -config_file lachesis_osso.conf 
               -mod_osso_url http://lachesis.shelman.int
    CLASSPATH=/home/oracle/OraHome_1/jlib/repository.jar:/home/oracle/OraHome_1/sso/lib/ossoca.jar:/home/oracle/OraHome_1/sso/lib/ossoreg.jar:/home/oracle/OraHome_1/lib/xmlparserv2.jar:/home/oracle/OraHome_1/jdbc/lib/classes12.jar:/home/oracle/OraHome_1/jdbc/lib/nls_charset12.jar:/home/oracle/OraHome_1/jlib/jndi.jar:/home/oracle/OraHome_1/jlib/ojmisc.jar:/home/oracle/OraHome_1/j2ee/home/jazn.jar:/home/oracle/OraHome_1/j2ee/home/jaas.jar:/home/oracle/OraHome_1/jdk/lib/rt.jar:/home/oracle/OraHome_1/jdk/lib/i18n.jar:.:/home/oracle/OraHome_1/sysman/webapps/emd/WEB-INF/lib/emd.jar:/home/oracle/OraHome_1/dcm/lib/dcm.jar:/home/oracle/OraHome_1/sysman/j2ee/lib/portalSMI.jar:/home/oracle/OraHome_1/jlib/emConfigInstall.jar:/home/oracle/OraHome_1/lib/dms.jar:/home/oracle/OraHome_1/opmn/lib/ons.jar:/home/oracle/OraHome_1/j2ee/home/oc4j.jar
    Parameters passed to SSO registration tool :
    param0:-oracle_home_path param1:/home/oracle/OraHome_1 param2:-oracle_home_path param3:/home/oracle/OraHome_1 param4:-config_mod_osso param5:TRUE param6:-site_name param7:lachesis.shelman.int param8:-remote_midtier param9:-config_file param10:lachesis_osso.conf param11:-mod_oso_url param12:http://lachesis.shelman.int
    -DinstallType=
    -DoldOracleHome=
    -DoldOHSUser=root
    Wed May 23 15:07:20 EEST 2007  Invalid argument -mod_oso_url
    Wed May 23 15:07:20 EEST 2007  Missing value for parameter: http://lachesis.shelman.int
    oracle@eudoxia:~/sso_reg> $ORACLE_HOME/sso/bin/ssoreg.sh -oracle_home_path $ORACLE_HOME -config_mod_osso TRUE -site_name lachesis.shelman.int -remote_midtier -config_file lachesis_osso.conf -mod_osso_url http://lachesis.shelman.int
    CLASSPATH=/home/oracle/OraHome_1/jlib/repository.jar:/home/oracle/OraHome_1/sso/lib/ossoca.jar:/home/oracle/OraHome_1/sso/lib/ossoreg.jar:/home/oracle/OraHome_1/lib/xmlparserv2.jar:/home/oracle/OraHome_1/jdbc/lib/classes12.jar:/home/oracle/OraHome_1/jdbc/lib/nls_charset12.jar:/home/oracle/OraHome_1/jlib/jndi.jar:/home/oracle/OraHome_1/jlib/ojmisc.jar:/home/oracle/OraHome_1/j2ee/home/jazn.jar:/home/oracle/OraHome_1/j2ee/home/jaas.jar:/home/oracle/OraHome_1/jdk/lib/rt.jar:/home/oracle/OraHome_1/jdk/lib/i18n.jar:.:/home/oracle/OraHome_1/sysman/webapps/emd/WEB-INF/lib/emd.jar:/home/oracle/OraHome_1/dcm/lib/dcm.jar:/home/oracle/OraHome_1/sysman/j2ee/lib/portalSMI.jar:/home/oracle/OraHome_1/jlib/emConfigInstall.jar:/home/oracle/OraHome_1/lib/dms.jar:/home/oracle/OraHome_1/opmn/lib/ons.jar:/home/oracle/OraHome_1/j2ee/home/oc4j.jar
    Parameters passed to SSO registration tool :
    param0:-oracle_home_path param1:/home/oracle/OraHome_1 param2:-oracle_home_path param3:/home/oracle/OraHome_1 param4:-config_mod_osso param5:TRUE param6:-site_name param7:lachesis.shelman.int param8:-remote_midtier param9:-config_file param10:lachesis_osso.conf param11:-mod_osso_url param12:http://lachesis.shelman.int
    -DinstallType=
    -DoldOracleHome=
    -DoldOHSUser=root
    Check /home/oracle/OraHome_1/sso/log/ssoreg.log for details of this registration
    SSO registration tool finished successfully.
    oracle@eudoxia:~/sso_reg>
    
  2. Now we have the file named lachesis_osso.conf that we need to copy to the actual host running the 10.1.3.x instance.
    oracle@eudoxia:~/sso_reg> scp lachesis_osso.conf oracle@lachesis:/home/oracle
    Password:
    lachesis_osso.conf                                                         100%  417     0.4KB/s   00:00
    oracle@eudoxia:~/sso_reg>
    
  3. Back in the middle tier host, we only need to run file osso1013 located in the $ORACLE_HOME/Apache/Apache/bin directory, passing it the new file as an argument.
    racle@lachesis:~> $ORACLE_HOME/Apache/Apache/bin/osso1013 lachesis_osso.conf
    
    /home/oracle/product/10.1.3.1/OracleAS_1/Apache/Apache/conf/httpd.conf successfully updated.
    /home/oracle/product/10.1.3.1/OracleAS_1/Apache/Apache/conf/mod_osso.conf successfully updated.
    
    oracle@lachesis:~>
    

Now when we want to SSO protect any deployed application we usually edit the file mod_sso.conf located in $ORACLE_HOME/Apache/Apache/conf. Let's suppose now that an already installed application uses a web content root like /MyApp. In this case users would invoke it via a URL like http://my_host:my_post/myApp.
Protecting this application with SSO requires that you enter the following in the mod_osso.file.
<Location /MyApp>
    require valid-user
    AuthType Basic
</Location>
As always bouncing the instance is the last step.

Oracle IAS 10g 10.1.3.x Enable Apache to run as root and set the default HTTP port to 80 (non SSL)

This is relatively easy and comes straight out of the Oracle Application Server Administrator's Guide. In order to set the HTTP listen port to value less than 1024 we need to set the Apache to run as root.
[oracle@barbara ~]$ su
Password: 

[root@barbara bin]#  cd $ORACLE_HOME/Apache/Apache/bin
[root@barbara bin]# chown root .apachectl 
[root@barbara bin]# chmod 6750 .apachectl
Logout from the root shell
[oracle@barbara ~]$ vi $ORACLE_HOME/Apache/Apache/conf/httpd.conf
locate the first listen directive. You should see a fragment like :
#
# Port: The port to which the standalone server listens. For
# ports < 1024, you will need httpd to be run as root initially.
#
# This port is used when starting without SSL
Port 7777
Listen 7777
Change both values to 80, save the file and restart the middle tier instance.
[oracle@barbara ~]$ opmnctl stopall
[oracle@barbara ~]$ opmnctl startall
opmnctl: starting opmn and all managed processes...
[oracle@barbara ~]$ 
The new Application server home page can then be accessed simply be typing http://myservername on your browser's address bar

Tuesday 22 May 2007

Oracle IAS 10g 10.1.3.1

I have just finished installing a development Oracle IAS 10g version 10.1.3.1 and from what I 've seen new instances are created with support for ADF already enabled. So instead of tampering with the XML files consider the upgrade to 10.1.3.x.

Making a new OC4J Instance ADF aware in Oracle IAS 10.1.3

... or simply copy shared library definitions from one OC4J instance to an other

When you create a new OC4J instance on an Oracle Application server 10g 10.1.3 using the createinstance utility, then the new instance does not have the ADF libraries installed and therefore you cannot deploy any ADF based applications that you usually create using JDeveloper.

To resolve this issue -- thanks to Oracle support -- you have to manually add references for the adf.*libraries to the new instance's server.xml file and add references to the bc4j application to both the server.xml and the default-web-site.xml. The correct configuration is only available in the default home instance created during installation, so we are going to copy the setup from there.

The detailed list of steps required are the following. let's suppose that the new oc4j instance name is OC4J_NEW.

  1. Shutdown the server.
  2. Open $ORACLE_HOME/j2ee/home/config/server.xml using any windowed text editor.
  3. Open $ORACLE_HOME/j2ee/OC4J_NEW/config/server.xml using any windowed text editor.
  4. Copy the two shared-library tags with name="adf.oracle.domain" and name="adf.generic.domain" found in the home/config/server.xml and paste them into the OC4J_NEW/config/server.xml after the last of the shared library tags already in the file. (The same technique can be used for practically copying any server library definitions from one instance to an other).
  5. Close the home/config/server.xml file.
  6. Move towards the end of the OC4J_NEW server.xml and locate a line like:
  7. <application name="ascontrol" path="../../home/applications/ascontrol.ear" parent="system" start="false"/> 
    
  8. insert a blank line after it and add the following :
  9. <application name="bc4j" path="../../../BC4J/redist/bc4j.ear" start="true"/>
    
  10. Close and save the OC4J_NEW server.xml file.
  11. Open the OC4J_NEW/config/default-web-site.xml file. Add a line like :
    <web-app application="bc4j" name="webapp" startup="true" root="/webapp"/> 
    
    right after the <default-web-app> tag located in the top. Close and save the file and restart the instance.In case of any typing errors, the instance log provides very detailed error messages -- at least it did so for me.

Tuesday 15 May 2007

Oracle ADF Committing master and relevant detail rows simultaneously

There is no doubt that using a trigger to provide unique id's from a database sequence is the best way to handle primary keys. (By the way, I wonder which version of Oracle database will provide an auto-increment data type like MySQL?) There are cases however that require you to create master and detail records in the application server memory and then commit everything simultaneously like in the case of an e-shop where you have to keep both the order header and lines uncommitted until the user finally decides to place the order.

In cases like these, using the DBSequence type for the corresponding entity object attribute might get you into trouble, like I did just yesterday. Theory says that the value of a DBSequence key attribute is a (unique) negative number that later becomes the value assigned by the database trigger. What I did, was try to create detail rows programatically but the master attribute reference for these rows became the negative DBSequence value assigned to the header line at the start of the transaction. So when I tried to do the final commit I got a very clear error explaining that the foreign key constraint for the detail rows was violated.

The only reliable way I found to get myself out of this was to turn back to my old JDeveloper 10g Handbook (published back in 2004) and dig out the following code to allow my entities to obtain an id value directly from the database sequence, thus moving the trigger code from the DB to the application server. So overriding the create method for my custom order header entity object gave me something like this :


import oracle.jbo.server.SequenceImpl;

  ...

  /**
   * Provide a new order id from the SQ_ORDERS database sequence.
   */
  protected void create(AttributeList attributeList)
  {
      super.create(attributeList);
    
      // get a new sequence value for the order ID
      SequenceImpl sqOrders = new SequenceImpl("SQ_ORDERS", getDBTransaction());
      setOrderId( sqOrders.getSequenceNumber());
  }

Friday 11 May 2007

Oracle ADF How to get the Date after n days and calculate the difference between two dates

I have used this little code fragment many times and each time I try to remember where -- and in which file -- was the last.

I guess that if I put it here, I will limit my search space significantly :-)

import oracle.jbo.domain.Date;
import oracle.jbo.domain.Number;
import java.sql.Timestamp;

...
static final long MILI_SECONDS_PER_DAY = 86400000;

    /**
     * @param startDate initial date to start counting from
     * @param nDays number of days can be begative
     * @return a Date object nDays after startdate
     */
    public static Date dateAfterNDays( Date startDate, int nDays)
    {
       if (startDate == null)
           startDate = new Date(Date.getCurrentDate());  // assume today

       Timestamp ts = startDate.timestampValue();
       long nextDatesSecs = ts.getTime() + (MILI_SECONDS_PER_DAY * nDays);
       return new Date( new Timestamp(nextDatesSecs));
    }

Here is an other example that calculates the number of days between two dates. The parameter dates are oracle.jbo.domain.Date and the return type is an oracle.jbo.domain.Number.

    /**
     * return the number of days between two dates
     */

    private Number dateDifference(InDays Date startDate, Date endDate)
    {
       if (startDate == null)
           startDate = new Date(Date.getCurrentDate()); // assume today

       if (endDate == null)
            endDate = new Date(Date.getCurrentDate());  // asume today again

       Timestamp tsStart = startDate.timestampValue();
       Timestamp tsEnd = endDate.timestampValue();

       long ndays = (tsEnd.getTime() - tsStart.getTime()) / MILI_SECONDS_PER_DAY;

       return new Number(ndays);
    }

Tuesday 1 May 2007

Linux: Synchronizing a directory tree via LAN with rsync

I keep two copies of my data -- at least I try to do that for the ones I care about like my mp3 files at home and my JDeveloper projects at work. One copy is on my local machine and the other on an other.one with a big hard disk. The command to do this is :

%> rsync -aruvzh  /src_dir user@remote_machine_ip:/dest_dir

This will add all files and directories contained below src_dir excatly under dest_dir. If you need ti remove files not contained in src_dir from dest_dir as well use the --delete option. So the previous command becomes.:

%> rsync -aruvzh --delete  /src_dir user@remote_machine_ip:/dest_dir

by the way, if you think that this is hard to remember and you need to do the synchronizing task often, then adding a line like

alias do_resync='rsync -aruvzh --delete /source_dir you@other_moahchine:/target_dir'

in your ~/.bashrc file, might be the answer, or at least it was/is for me :-)