In NSO 4.2 the NAVU has been changed to fully support writable operational data transactions via MAAPI. For this reason the NavuContext(Cdb) and NavuContext(CdbSession) constructors has been deprecated. The NavuCdbXXXSubscribers was deprecated in NSO 4.2 and finally removed in NSO 5.1 and the strong recommendation is to change these to plain Cdb subscribers and if necessary in diff iterators make use of KeyPath2NavuNode.getNode() to be able to reuse old NavuCdbDiffIterator code.
The following is an example on how to make these changes. The prerequisite is an NavuCdbSubscriber that is used as an application component in a package.
We start with the following code which is part of the web-site-service example.
public class CdbUpdateHandler implements ApplicationComponent, NavuCdbConfigDiffIterate { private static Logger LOGGER = Logger.getLogger(CdbUpdateHandler.class); private static Logger PROPLOG = Logger.getLogger("PROPLOG"); private NavuCdbSubscriber navuCfgSubscriber; private void configurePropLogger() throws IOException { SimpleLayout layout = new SimpleLayout(); SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd"); String fileName = "logs/props.log"; FileAppender appender = new FileAppender(layout, fileName); PROPLOG.addAppender(appender); PROPLOG.setAdditivity(false); PROPLOG.setLevel(Level.DEBUG); } @Override public void init() throws Exception { try { configurePropLogger(); NcsMain ncsMain = NcsMain.getInstance(); ConfPath p = new ConfPath("/ncs:services/properties/wsp:web-site"); navuCfgSubscriber = NavuCdbSubscribers.configSubscriber(ncsMain.getNcsHost(), ncsMain.getNcsPort()); navuCfgSubscriber.register(this, p); } catch (Exception e) { throw new RuntimeException("Fail in init", e); } } @Override public void run() { navuCfgSubscriber.subscriberStart(); LOGGER.info("subscribed: ready"); } @Override public void finish() throws Exception { try { navuCfgSubscriber.subscriberStop(); navuCfgSubscriber.awaitStopped(); } catch (InterruptedException e) { LOGGER.error("Exception in shutdownSubscriber", e); } finally { navuCfgSubscriber.executor().shutdown(); } } public void iterate(NavuCdbSubscriptionConfigContext ctx){ try { NavuNode node = ctx.getNode(); DiffIterateOperFlag op = ctx.getOperFlag(); switch (op) { case MOP_CREATED: PROPLOG.info("CREATED : " + node.getKeyPath()); break; case MOP_VALUE_SET: PROPLOG.info("SET : " + node.getKeyPath()); PROPLOG.info("VALUE : " + ctx.getNewValue()); break; case MOP_MODIFIED: PROPLOG.info("MODIFIED : " + node.getKeyPath()); break; case MOP_DELETED: PROPLOG.info("DELETED : " + node.getKeyPath()); break; } } catch (Exception e) { LOGGER.error("",e); } ctx.iterContinue(); } }
First change the use of the NavuCdbConfigDiffIterate interface to the plain CdbDiffIterate interface instead:
9c9,10 < public class CdbUpdateHandler implements ApplicationComponent, CdbDiffIterate { --- > public class CdbUpdateHandler implements ApplicationComponent, > NavuCdbConfigDiffIterate {
Make use of a Cdb instance for the subscription and a Maapi instance for a NavuContext that will be used in the iterate method. We also define a requestStop flag to signal the finish of the subscription: We remove the reference to the NavuCdbSubscriber:
12,19c13 < < @Resource(type=ResourceType.CDB, scope=Scope.INSTANCE) < private Cdb cdb; < private CdbSubscription cdbsubscr; < @Resource(type=ResourceType.MAAPI, scope=Scope.INSTANCE) < private Maapi maapi; < private NavuContext ncontext; < private boolean requestStop = false; --- > private NavuCdbSubscriber navuCfgSubscriber;
In the application components init() method we start a user session for the Maapi and define the cdb subscription. The NavuCdbSubscribers registration is removed:
34,37d27 < maapi.startUserSession("system", InetAddress.getByName(null), < "system", new String[]{}, < MaapiUserSessionFlag.PROTO_TCP); < ncontext = new NavuContext(maapi); 39,42c29,34 < cdbsubscr = cdb.newSubscription(); < cdbsubscr.subscribe(1, 0, "/ncs:services/properties/wsp:web-site"); < cdbsubscr.subscribeDone(); < requestStop = false; --- > NcsMain ncsMain = NcsMain.getInstance(); > ConfPath p = new ConfPath("/ncs:services/properties/wsp:web-site"); > navuCfgSubscriber = > NavuCdbSubscribers.configSubscriber(ncsMain.getNcsHost(), > ncsMain.getNcsPort()); > navuCfgSubscriber.register(this, p);
In the application components run() method we remove the NavuCdbSubscriber start and replace it with a read loop for the plain Cdb subscriber:
50a43 > navuCfgSubscriber.subscriberStart(); 52,69d44 < try { < while (!requestStop) { < try { < int[] spoints = cdbsubscr.read(); < ncontext.startRunningTrans(Conf.MODE_READ); < cdbsubscr.diffIterate(spoints[0], this); < int th = ncontext.clearTrans(); < if (th > 0) { < maapi.finishTrans(th); < } < } finally { < cdbsubscr.sync(CdbSubscriptionSyncType.DONE_PRIORITY); < } < } < } catch (Throwable e) { < LOGGER.error("Error in subscription:", e); < } < requestStop = false;
In the application components finish() method we set the requestStop flag, finish the maapi user session and unregister the resources. Here the ResourceManager.unregisterResources will close both the Cdb and Maapi sockets. We remove the earlier NavuCdbSubscriber stopping code:
75,78d49 < requestStop = true; < try { < maapi.endUserSession(); < } catch (Throwable ignore) {} 80,81c51,57 < ResourceManager.unregisterResources(this); < } catch (Throwable ignore) {} --- > navuCfgSubscriber.subscriberStop(); > navuCfgSubscriber.awaitStopped(); > } catch (InterruptedException e) { > LOGGER.error("Exception in shutdownSubscriber", e); > } finally { > navuCfgSubscriber.executor().shutdown(); > }
We change the iterate method to the CdbDiffIterate interface:
84,88c60 < public DiffIterateResultFlag iterate(ConfObject[] kp, < DiffIterateOperFlag op, < ConfObject oldValue, < ConfObject newValue, < Object initstate) { --- > public void iterate(NavuCdbSubscriptionConfigContext ctx){
In the iterate() method we make use of the KeyPath2NavuNode.getNode() to obtain a NavuNode for the subscription entry:
90c62 < NavuNode node = KeyPath2NavuNode.getNode(kp, ncontext); --- > NavuNode node = ctx.getNode();
In the iterate() method obtain the DiffIterateOperFlag and the newValue directly and we change we need to return with the DiffIterateResultFlag directly:
91a64 > DiffIterateOperFlag op = ctx.getOperFlag(); 98c71 < PROPLOG.info("VALUE : " + newValue); --- > PROPLOG.info("VALUE : " + ctx.getNewValue()); 110c83 < return DiffIterateResultFlag.ITER_CONTINUE; --- > ctx.iterContinue();
The resulting code should look the as the following:
public class CdbUpdateHandler implements ApplicationComponent, CdbDiffIterate { private static Logger LOGGER = Logger.getLogger(CdbUpdateHandler.class); private static Logger PROPLOG = Logger.getLogger("PROPLOG"); @Resource(type=ResourceType.CDB, scope=Scope.INSTANCE) private Cdb cdb; private CdbSubscription cdbsubscr; @Resource(type=ResourceType.MAAPI, scope=Scope.INSTANCE) private Maapi maapi; private NavuContext ncontext; private boolean requestStop = false; private void configurePropLogger() throws IOException { SimpleLayout layout = new SimpleLayout(); SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd"); String fileName = "logs/props.log"; FileAppender appender = new FileAppender(layout, fileName); PROPLOG.addAppender(appender); PROPLOG.setAdditivity(false); PROPLOG.setLevel(Level.DEBUG); } @Override public void init() throws Exception { try { maapi.startUserSession("system", InetAddress.getByName(null), "system", new String[]{}, MaapiUserSessionFlag.PROTO_TCP); ncontext = new NavuContext(maapi); configurePropLogger(); cdbsubscr = cdb.newSubscription(); cdbsubscr.subscribe(1, 0, "/ncs:services/properties/wsp:web-site"); cdbsubscr.subscribeDone(); requestStop = false; } catch (Exception e) { throw new RuntimeException("Fail in init", e); } } @Override public void run() { LOGGER.info("subscribed: ready"); try { while (!requestStop) { try { int[] spoints = cdbsubscr.read(); ncontext.startRunningTrans(Conf.MODE_READ); cdbsubscr.diffIterate(spoints[0], this); int th = ncontext.clearTrans(); if (th > 0) { maapi.finishTrans(th); } } finally { cdbsubscr.sync(CdbSubscriptionSyncType.DONE_PRIORITY); } } } catch (Throwable e) { LOGGER.error("Error in subscription:", e); } requestStop = false; } @Override public void finish() throws Exception { requestStop = true; try { maapi.endUserSession(); } catch (Throwable ignore) {} try { ResourceManager.unregisterResources(this); } catch (Throwable ignore) {} } public DiffIterateResultFlag iterate(ConfObject[] kp, DiffIterateOperFlag op, ConfObject oldValue, ConfObject newValue, Object initstate) { try { NavuNode node = KeyPath2NavuNode.getNode(kp, ncontext); switch (op) { case MOP_CREATED: PROPLOG.info("CREATED : " + node.getKeyPath()); break; case MOP_VALUE_SET: PROPLOG.info("SET : " + node.getKeyPath()); PROPLOG.info("VALUE : " + newValue); break; case MOP_MODIFIED: PROPLOG.info("MODIFIED : " + node.getKeyPath()); break; case MOP_DELETED: PROPLOG.info("DELETED : " + node.getKeyPath()); break; } } catch (Exception e) { LOGGER.error("",e); } return DiffIterateResultFlag.ITER_CONTINUE; } }