SpinnerSimpleDateModel

Here is the code for a JSpinnerModel that handles Date objects in simple format (e.g. ‘dd/MM/yyyy’). It extends a SpinnerDateModel so most of the code is based on that class. This class assumes that values are separated by a slash (/). The reason why I created this was based on a client’s requirement where I could only display the date in simple format and select the calendar using a JSpinner:

/**
 * A SpinnerSimpleDateModel for sequences of formatted Dates.
 * in simple format(e.g. "dd/MM/yyyy")
 *
 * @author William Mora
 * @version 1.0
 */
public class SpinnerSimpleDateModel extends SpinnerDateModel {

    private Comparable start, end;
    private Date value;
    private int calendarField;
    private SimpleDateFormat dateFormat;

    private boolean calendarFieldOK(int calendarField) {
        switch (calendarField) {
            case Calendar.DATE:
            case Calendar.YEAR:
            case Calendar.MONTH:
                return true;
            default:
                return false;
        }
    }

    /**
     * Creates an instance of SpinnerSimpleDateModel
     *
     * @param value         Initial date for the model
     * @param start         Minimum date for the model
     * @param end           Maximum date for the model
     * @param calendarField The interval desired for next and previous values.
     *                      The options are:
     *                      Calendar.DATE - Day of the month
     *                      Calendar.MONTH - Month
     *                      Calendar.YEAR - Year
     * @param dateFormat    A format specified by an instance of SimpleDateFormat
     */
    public SpinnerSimpleDateModel(Date value, Comparable start, Comparable end, int calendarField, SimpleDateFormat dateFormat) {
        this.dateFormat = dateFormat;
        if (value == null) {
            throw new IllegalArgumentException("value is null");
        }
        if (!calendarFieldOK(calendarField)) {
            throw new IllegalArgumentException("invalid calendarField");
        }
        if ( !(((start == null) || (start.compareTo(value) & lt;=0))&&
        ((end == null) || (end.compareTo(value) & gt;=0)))){
            throw new IllegalArgumentException("(start <= value <= end) is false");
        }
        this.value = value;
        this.start = start;
        this.end = end;
        this.calendarField = calendarField;
    }

    @Override
    public void setStart(Comparable start) {
        if ((start == null) ? (this.start != null) : !start.equals(this.start)) {
            this.start = start;
            fireStateChanged();
        }
    }

    @Override
    public void setEnd(Comparable end) {
        if ((end == null) ? (this.end != null) : !end.equals(this.end)) {
            this.end = end;
            fireStateChanged();
        }
    }

    @Override
    public void setCalendarField(int calendarField) {
        if (!calendarFieldOK(calendarField)) {
            throw new IllegalArgumentException("invalid calendarField");
        }
        if (calendarField != this.calendarField) {
            this.calendarField = calendarField;
            fireStateChanged();
        }
    }

    @Override
    public Comparable getEnd() {
        return end;
    }

    @Override
    public Object getNextValue() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(value);
        cal.add(calendarField, 1);
        Date next = cal.getTime();
        return (end == null) || (end.compareTo(next) & gt;=0)?next:
        null;
    }

    @Override
    public Object getPreviousValue() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(value);
        cal.add(calendarField, -1);
        Date prev = cal.getTime();
        return ((start == null) || (start.compareTo((prev)) <= 0)) ? prev : null;
    }

    @Override
    public Object getValue() {
        return value;
    }

    @Override
    public void setValue(Object value) {
        if (value == null) {
            throw new NullPointerException("Date is null!");
        } else {
            if ((value instanceof String) && ((String) value).matches("[0-9]+[/][0-9]+[/][0-9]+")) {
                String date = ((String) value);
                int day = Integer.parseInt(date.substring(0, 2));
                int month = Integer.parseInt(date.substring(3, 5));
                int year = Integer.parseInt(date.substring(6));
                Calendar cal = Calendar.getInstance();
                //Month-1 because is zero-based
                cal.set(year, month - 1, day);
                this.value = cal.getTime();
            }
            if (value instanceof Date) {
                if (!dateFormat.format((Date) value).equals(dateFormat.format(this.value))) {
                    String temp = dateFormat.format((Date) value);
                    this.setValue(temp);
                    fireStateChanged();
                }
            }
        }

    }
}

Now the model can be used for any JSpinner. To create an instance for this class, the following will work:

SpinnerSimpleDateModel spinnerModel = new SpinnerSimpleDateModel(new Date(), null, null, Calendar.DATE, new SimpleDateFormat("dd/MM/yyyy"));

Then, set the editor of the JSpinner object to show the same format specified for the SpinnerSimpleDateModel object like the following:

JSpinner spinner1 = new javax.swing.JSpinner();
spinner1.setModel(spinnerModel);
spinner1.setEditor(new javax.swing.JSpinner.DateEditor(spinner1, "dd/MM/yyyy"));

Hope someone finds this useful. An advantage of this is to manipulate date formats as you wish regardless of the OS or region.

Advertisements
Posted in Uncategorized

Installing Oracle Application Server 10g on Windows Server 2003 SP2

If you try to install the Oracle Application Server 10g (9.0.4) on a Windows Server 2003 SP2, you may encounter an error when the installer tries to configure the OC4J instances with the following:

Deploying application 'ADFBCManager' to OC4J instance 'home'.
FAILED!
ERROR: Caught exception while deploying 'ADFBCManager' to 'home':
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at oracle.j2ee.tools.deploy.Oc4jDeploy.doDeploy(Unknown Source)
at oracle.j2ee.tools.deploy.Oc4jDeploy.execute(Unknown Source)
at oracle.j2ee.tools.deploy.Oc4jDeploy.deploy(Unknown Source)
at oracle.j2ee.tools.deploy.Oc4jDeploy.main(Unknown Source)
Caused by: com.evermind.client.orion.AdminCommandException: Deploy error: deploy failed!: ; nested exception is:
oracle.oc4j.admin.internal.DeployerException: Error initializing ejb-module; Exception Error in application ADFBCManager: Error loading package at file:/C:/oraOAS10g/j2ee/home/applications/ADFBCManager/bc4joembean.jar,
Error compiling C:\oraOAS10g\j2ee\home\applications\ADFBCManager\bc4joembean.jar: Syntax error in source
at com.evermind.client.orion.DeployCommand.execute(DeployCommand.java:90)
at com.evermind.client.orion.Oc4jAdminConsole.executeCommand(Oc4jAdminConsole.java:139)
... 8 more
...

The reason for this is because one of Microsoft’s security updates (MS09-012 or KB956572). When the patch is installed, it prevents any JAVA Virtual Machine to run properly.
If you encounter this issue during the OAS installation (or with any other application running a JVM), do a clean deinstall of the application server. Next, download Microsoft’s patch to solve this issue (click here to download and remember to download it in the correct language). Restart your server after the patch is installed, run the Oracle Universal Installer again to install the Oracle Application Server and the installation should be successful now.

Tagged with: , , , , ,
Posted in Database Administration, Tech

Duplicate Oracle Constraints

If you have ever used the Oracle import utility, your database has system generated constraint names (ex: SYS_C00641321), and you did not specify CONSTRAINTS=N during the import then chances are you have duplicate constraints for pretty much every constraint except for any PRIMARY KEY, FOREIGN KEY and user generated constraint names.

I recently stumbled upon a database that had performance issues and one of the things I noticed was that almost every single constraint was repeated up to 10 times. Most of the duplicates were NOT NULL constraints, which is kind of expected since people tend to create NOT NULL constraints anonymously such as the following:

CREATE TABLE tab1
(col1  VARCHAR(2) NOT NULL,
col2  VARCHAR(30) NOT NULL);

That statement will create 2 NOT NULL constraints with a system generated name (ex: SYS_C00641322 and SYS_C00641323). If the schema that owns that table is exported and then imported to another schema, it will create two additional NOT NULL constraints since it recreates the table running the exact same command shown above.

That could be prevented by having user generated constraint names:

CREATE TABLE tab1
(col1  VARCHAR(2) CONSTRAINT COL1_NN NOT NULL,
col2  VARCHAR(30) CONSTRAINT COL2_NN NOT NULL);

If the schema that owns that table is exported and then imported to another schema, it does not create duplicate any constraints since the system is forced to specify the constraint name at table creation.

Here is my script to identify the duplicate constraints and then generate a script to drop those unnecessary constraints. The logic is to create two temporary tables: One that lists all the constraints (except for PRIMARY KEY and FOREIGN KEY constraints) that should be in the database and another table where I put all the necessary information for the constraints that need to be dropped. Once the table DUMP_CONSTRAINTS is populated, a script is generated to drop all those constraints. Finally, I dropped the temporary tables that I used:

CREATE GLOBAL TEMPORARY TABLE temp_constraints
(table_name       varchar2(30),
constraint_name  varchar2(30),
search_condition varchar2(2000),
CONSTRAINT temp_constraints_pk PRIMARY KEY (table_name, search_condition))
/
CREATE GLOBAL TEMPORARY TABLE dump_constraints
(table_name       varchar2(30),
constraint_name  varchar2(30),
search_condition varchar2(2000))
/
DECLARE
tabName   VARCHAR2(30)    := NULL;
conName   VARCHAR2(30)    := NULL;
seaCond   VARCHAR2(2000)  := NULL;
CURSOR c_cursor IS
   SELECT table_name,constraint_name,search_condition
   FROM user_constraints
   WHERE constraint_type NOT IN ('P','R')
   AND search_condition IS NOT NULL
   ORDER BY table_name;
BEGIN
  dbms_output.enable(null); -- To prevent a buffer overflow
  FOR c IN c_cursor LOOP
  BEGIN
     tabName := c.table_name;
     conName := c.constraint_name;
     seaCond := c.search_condition;
     INSERT INTO temp_constraints values(tabName,conName,seaCond);
     EXCEPTION
     WHEN DUP_VAL_ON_INDEX THEN
      BEGIN
       INSERT INTO dump_constraints values(tabName,conName,seaCond);
 END;
     WHEN OTHERS THEN dbms_output.put_line('Another exception: '||tabName||' Search condition: '||seaCond);  -- For debugging purposes
   END;
END LOOP;
END;
/
SPOOL 'C:\dump_duplicate_constraints'.sql
SET verify OFF
SET pages 0
SET serveroutput ON
SELECT 'ALTER TABLE '||table_name||' DROP CONSTRAINT '||constraint_name||';'
FROM dump_constraints;
/
SPOOL OFF
SET pages 10000
DROP TABLE temp_constraints CASCADE CONSTRAINTS;
/
DROP TABLE dump_constraints CASCADE CONSTRAINTS;
/

So, how to prevent this from ever happening again? You could either:
1) Make sure that an import does not import any constraints (just set CONSTRAINTS=N when importing)
2) Make sure you properly name ALL constraints. Do not let the system generate a constraint name for you (like previously mentioned)

I hope this helps anyone out there. Feel free to leave a comment if you have any questions.

Tagged with: , , , , , , ,
Posted in Database Administration

Password Case Sensitivity in Oracle 11g

Oracle 11g now sets the password case sensitivity setting to TRUE by default. If you are running any application that connects to an earlier version of an Oracle database, chances are you are sending the connect string in all caps within the application (ex: USER/USER@ORCL11G when it really should be user/user@orcl11g). Make sure you are aware of this when developing your app and if the case is that you want to have case sensitive passwords, use double quotes to enclose the password string (ex: USER/”user”@ORCL11G). To disable password case sensitivity, just change the value of the system parameter sec_case_sensitive_logon:

alter system set sec_case_sensitive_logon = FALSE;

Where FALSE disables password case sensitivity and TRUE enables it.

Tagged with: , , , , ,
Posted in Database Administration

Running an Oracle Forms Applet on Windows 7

I was trying to run my application built in Oracle Forms and Reports on a new laptop with Windows 7. However, when running the Java forms applet, the applet’s graphics stayed frozen and I was not able to see my application properly.

This problem is caused due to the graphics card running on the computer running Windows 7. To run certain applications, Windows 7 must change its theme back to Windows 7 Basic (I believe it was the same issue with Vista). So, basically, the graphics card is too much for the Java applet to handle.

A quick, simple solution is to modify the java.exe found in %ORACLE_HOME%\jdk\bin so it runs with only 256 colors (8 bits). The problem with this solution is that the computer looks really bad since it is only running on 256 colors (that’s what the original Nintendo used!). I needed to run the applet in order to show my application to future clients, so I needed the application to run on 32 bits. After looking at several settings that may cause the issue, I realized that if I quickly refreshed the screen once the applet was initialized (e.g. change the monitor display settings so it runs on 16 bits and then cancel the changes), the applet would run without any problems. So, I needed to somehow refresh the monitor once the applet started in order to make my application run on 32 bits without the image staying frozen.

Although it was not the most elegant solution (I was on a deadline!), I decided to include a function in the html that launches my application so it runs a batch file that quickly refreshes the screen. This is how I did it:

1) Downloaded the command-line tool NirCmd, which allows you to change the monitor settings without the user interface. You can download the tool here.

2) Unzipped the nircmd executables to c:\Windows

3) Created the .bat (I saved it as screenRefresher.bat) file to be launched with the application with the lines:

echo off
nircmd setdisplay 1360 768 16
nircmd setdisplay 1360 768 32

Of course, the 1360 768 should correspond to your particular screen settings. What the batch file is basically doing is quickly changing the screen display colors to 16 bits and then to 32 bits. This is just a dummy operation so the screen refreshes at runtime.

4) Finally, edited the html to run the batch file when loading. This is the section I modified:

<html>
<head>
<script type="text/javascript">
function refreshMonitor()
{
WshShell = new ActiveXObject("WScript.Shell");
WshShell.Run ('file://C:/appLocation/html/screenRefresher.bat',1,true);
}
</script>
<title>AppName - Welcome</title>
</head>
<body onload="refreshMonitor();">
<!--Body content-->
<body>
<html>

5) Changed the security settings of Internet Explorer so it allows running Active X objects

6) And done! Now I can start the instance, run the application and while the applet is loading the batch file will execute simultaneously. The applet now runs on 32 bits without any problems!

NOTE: This has only been tested with Internet Explorer and this is not a solution suggested in any way by Oracle. It is just a workaround I implemented for my application to run on Windows 7

Tagged with: , , , , , , , , ,
Posted in Database Administration, Tech

SQL: Exists Condition

The SQL EXISTS condition is a boolean function that returns true if the condition is met. The syntax is pretty simple:

SELECT * FROM TABLE WHERE EXISTS(subquery);

Alternatively, you can use NOT EXISTS(subquery). An example of the function is the following:

SELECT utc.table_name
FROM user_tab_cols utc
WHERE utc.column_name='ACCOUNTID'
AND NOT EXISTS(SELECT uc.table_name
FROM user_constraints uc
WHERE uc.table_name=utc.table_name
AND uc.r_constraint_name='SYS_C00229824')
ORDER BY utc.table_name;

The query looks for all the tables that contain the column ACCOUNTID and from those tables, only get the ones that don’t make reference to the constraint SYS_C00229824.

Tagged with: , ,
Posted in Database Administration

How to Modify Swap Size – Ubuntu 10.04

When installing Ubuntu, I was never asked about the desired size for my swap size. Oracle recommends to use at least 2GB of memory in order to create a database, let alone run it.
With help from this excellent post from LinuxReaders, I expanded my swap size to 2GB (again, Oracle’s recommended size for 11g) by executing the following:

$ dd if=/dev/zero of=/tmp/swapfile bs=1MB count=2048
2048+0 records in
2048+0 records out
2048000000 bytes (2.0 GB) copied, 36.257 s, 56.5 MB/s
$ mkswap /tmp/swapfile
mkswap: /tmp/swapfile: warning: don't erase bootbits sectors
on whole disk. Use -f to force.
Setting up swapspace version 1, size = 1999996 KiB
no label, UUID=aa8617a8-9500-498e-90da-f5164190ad00
$ sudo swapon /tmp/swapfile

Checked my swap memory with free -m
total used free shared buffers cached
Mem: 3895 3841 53 0 1008 1799
-/+ buffers/cache: 1033 2861
Swap: 2208 0 2208

And made the swap size permanent by adding the following to /etc/fstab:

/tmp/swapfile swap swap defaults 0 0

Cheers!

Tagged with: , , , , , ,
Posted in Tech

Error: Please make sure the Twitter account is public.