1

I am using following code for registering and listening to Oracle database change notifications. This code is working fine when i run it as a standalone java program. It is receiving the notification from the database and printing as expected.

  public class DBChangeNotification {
         
    static final String USERNAME = "XXX";
    static final String PASSWORD = "YYY";
    static String URL = "jdbc:oracle:thin:@xxxx:xxxx:xxxx";

    public static void main(String[] args) {
        DBChangeNotification demo = new DBChangeNotification();
        try {
            demo.run();
        } catch (SQLException mainSQLException) {
            mainSQLException.printStackTrace();
        }
    }
    
    public void run() throws SQLException {
        OracleConnection conn = connect();
        Properties prop = new Properties();
        prop.setProperty(OracleConnection.DCN_NOTIFY_ROWIDS, "true");
        prop.setProperty(OracleConnection.DCN_QUERY_CHANGE_NOTIFICATION, "true");
        prop.setProperty(OracleConnection.DCN_BEST_EFFORT, "true");

        DatabaseChangeRegistration dcr = conn.registerDatabaseChangeNotification(prop);
        try {
            // add the listenerr:
            DCNDemoListener list = new DCNDemoListener(this);
            dcr.addListener(list);

            // second step: add objects in the registration:
            Statement stmt = conn.createStatement();
            // associate the statement with the registration:
            ((OracleStatement) stmt).setDatabaseChangeRegistration(dcr);
            ResultSet rs = stmt.executeQuery("select * from xxxxxxxx where yyyy='zzzzz'");
            while (rs.next()) {
            }
            String[] tableNames = dcr.getTables();
            for (int i = 0; i < tableNames.length; i++) {
                System.out.println(tableNames[i] + " is part of the registration.");
            }
            rs.close();
            stmt.close();
        } catch (SQLException ex) {
            // if an exception occurs, we need to close the registration in order
            // to interrupt the thread otherwise it will be hanging around.
            if (conn != null) {
                conn.unregisterDatabaseChangeNotification(dcr);
            }
            ex.printStackTrace();
            throw ex;
        } finally {
            try {
                // Note that we close the connection!
                conn.close();
            } catch (Exception innerex) {
                innerex.printStackTrace();
            }
        }
    }
    /**
     * Creates a connection the database.
     */
    OracleConnection connect() throws SQLException {
        OracleDriver dr = new OracleDriver();
        Properties prop = new Properties();
        prop.setProperty("user", DBChangeNotification.USERNAME);
        prop.setProperty("password", DBChangeNotification.PASSWORD);
        return (OracleConnection) dr.connect(DBChangeNotification.URL, prop);
    }
}

/**
 * DCN listener: it prints out the event details in stdout.
 */
class DCNDemoListener implements DatabaseChangeListener {

    DBChangeNotification demo;
    DCNDemoListener(DBChangeNotification dem) {
        System.out.println("DCNDemoListener");
        demo = dem;
    }
    @Override
    public void onDatabaseChangeNotification(DatabaseChangeEvent e) {
        Thread t = Thread.currentThread();
        System.out.println("DCNDemoListener: got an event (" + this + " running on thread " + t + ")");
        System.out.println(e.toString());
        synchronized (demo) {
            demo.notify();
        }
    }
}

My requirement is to use this feature in a web application. Web application when started in the server, has to listen to data change notifications (may be on a separate thread) and notify the application through a websocket client. I have added the following code in contextInitialized method of servlet context listener, so that it will start as soon as the application starts.

public class MyServletContextListener implements ServletContextListener {
 DBChangeNotification demo;
 
  @Override
  public void contextDestroyed(ServletContextEvent arg0) {
    //Notification that the servlet context is about to be shut down. 
  }

  @Override
  public void contextInitialized(ServletContextEvent arg0) {
      demo = new DBChangeNotification();
        try {
            demo.run();
        } catch (SQLException mainSQLException) {
            mainSQLException.printStackTrace();
        }
  }
}

I did not see any notifications received by the web application when database change event occurs in the registered table. Please help me in resolving the issue. I do not know whether this is a correct approach or not.... may please suggest any alternative except continuous polling. I need to start something in the server as soon as i receive notification from database. Thank you.

1 Answer 1

0

It might be that you're running your code on an Oracle instance that doesn't have the Notification API available. Check this SO for more info

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.