Friday 2 February 2018

Using Zookeeper Nodes as Storage Units in Springboot application

This post is about my experiment on storing Distributed Atomic Long(DAL) in the Zookeeper Nodes.  Not that there are already enough blogs on this topic, The DAL comes out as out of the box recipe from the Curator Framework.
Here, we use Curator Framework to  handle all zookeeper operations. Here's a simple springboot curator config. Kept is super simple, the list of zookeeper servers come from app.properties, with exponential retry policy.  Once the client is created, we verify the connection by checking for "/" path.

@Configuration
public class CuratorConfig {

  @Value("${zookeeper.connection}")
  private String zookeeperServers;

  private final Logger logger = LoggerFactory.getLogger(this.getClass());
 
  @Bean
  @Qualifier("curatorConfig")
  CuratorFramework getCurratorFramework() {
   
    final CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder();
    builder.connectString(zookeeperServers);
    builder.retryPolicy(new ExponentialBackoffRetry(10, 100, 10000));
    builder.sessionTimeoutMs(30000);
    CuratorFramework client = builder.build();       
    client.start();
    logger.info("Waiting for curator to create a connection");
    try {
      client.blockUntilConnected();
      client.checkExists().forPath("/");
    } catch (Exception ie) {
      logger.error("Couldn't test zookeeper connection", ie);
    }
    logger.info("Zookeeper client for curator created !"); 
    return client;
  }

}





We can now write a util that recursively creates ZK nodes. Also, it has methods to create a new DAL.  Given a path say "path/to/zookeeper/node", I'm splitting them into individual node path and create a node a Persistent Node for it.  I was getting a "" node after split, that's why I'm including a condition to track the "" node.  The zookeeperConnection (CuratorFramework) is a springboot bean described in the code above.  I'm creating a Persistent Node, you can create  Ephemeral Storage as well.


public class ZookeeperUtil {

  public static void recursivelyCreateZKNodes(CuratorFramework zookeeperConnection, String path) throws InterruptedException, Exception {
    String prefix = "";
    String[] nodes = path.split("/");
    for (String node : nodes) {
      if (node.equals("")) {
        continue;
      }
      prefix += "/" + node;
      if (zookeeperConnection.checkExists().forPath(prefix) != null) {
        continue;
      }
      PersistentNode pnds = new PersistentNode(zookeeperConnection, CreateMode.PERSISTENT, false, prefix, "".getBytes());
      pnds.start();
      pnds.waitForInitialCreate(3, TimeUnit.SECONDS);
    }

  }

  public static Boolean deleteZKNode(CuratorFramework zookeeperConnection, String path) throws Exception {
    if (zookeeperConnection.checkExists().forPath(path) == null) {
      return Boolean.FALSE;
    }
    zookeeperConnection.delete().forPath(path);
    return Boolean.TRUE;
  }

  public static DistributedAtomicLong createNewDAL(CuratorFramework zookeeperConnection, String path) throws Exception {
    DistributedAtomicLong al = new DistributedAtomicLong(zookeeperConnection,
            path, new BoundedExponentialBackoffRetry(30000, 60000, 100));
    al.trySet(0L);
    return al;
  }

}

Once this is done,
1. recursively create ZK Node, use
        ZookeeperUtil.recursivelyCreateZKNodes(zookeeperConnection, requiredZookeeperNodePath);

2. Create a new DAL
      ZookeeperUtil.createNewDAL(zookeeperConnection, createdZookeeperNodePath);

Store the DAL in a bean, and we should be good call increment on it or trySet. Additionally you can put the increment and trySet in the Zookeeper Utils as well. We should be good to Rock and Roll!




Friday 8 December 2017

Oracle ADF Essentials/ Oracle ADF with MYSQL

Using Oracle ADF along with MYSQL can be a tricky since it was originally designed to work with Oracle Database. Like we understand that there are some trivial differences to certain operators across both engines.

Consider that you are using a view criteria that uses 'Contains' or 'Begins With' conditions for the bind variables.  MySQL doesn't support the pipe operator for concatenation out of the box.

The issue and solution is articulated here. One solution is to SET sql_mode='PIPES_AS_CONCAT';. This will fix the engine itself.
If you have additional constraints or dependent queries due to which you can't change the engine, here's another solution.

Let's take a User ViewObject with a user search view criteria, looks like the screenshot below



Create a Custom Implentation that extends the ViewObjectImpl class and overrides buildQuery method.

Let's dive into the code real quick

public class CustomVOImpl extends ViewObjectImpl {
    public CustomVOImpl(String string, ViewDefImpl viewDefImpl) {
        super(string, viewDefImpl);
    }

    public CustomVOImpl() {
        super();
    }
   
    @Override
     protected String buildQuery(int noUserParams, boolean forRowCount)
     {
       String query = super.buildQuery(noUserParams, forRowCount);
       if (query!=null) {
         query = query.replace( "( ? || '%')", " (CONCAT( ?, '%' ) )");
         query = query.replace( "('%' || ? || '%')", " (CONCAT('%', ?, '%' ) )");
       }
       //System.out.println("Updated query"+query);
       return query;
     }

     @Override
     protected String buildQuery(int noUserParams, boolean forRowCount, String selClause, String fromClause, String whereClause, int subQueryLevel)
     {
       String query = super.buildQuery(noUserParams, forRowCount, selClause, fromClause, whereClause, subQueryLevel);
       if (query!=null) {
           query = query.replace( "( ? || '%')", " (CONCAT( ?, '%' ) )");
           query = query.replace( "('%' || ? || '%')", " (CONCAT('%', ?, '%' ) )");
       }
        // System.out.println("Updated query"+query);
       return query;
     }
}
To explain in detail, query.replace( "( ? || '%')", " (CONCAT( ?, '%' ) )"). The '?' is where our bind parameter plugs itself in. Now replacing pipe operator with MySQL concat looks like (CONCAT( ?, '%' ) ). This concatenates bind parameter with a trailing '%' wildcard character.
Likewise to '%' || ? || '%' translates to (CONCAT('%', ?, '%' ) ).

Finally don't forget to incorporate this change in your ViewObject.!


 I did not find anything else that got funny with ADF Essentials + MySQL with Integrated WLS. Had to do some additional configs on Glassfish which I will explain it in a different blog post.



Tuesday 7 March 2017

Getting selected Rows in Oracle APEX Interactive Grid

I tried doing lot of things!! A lot, indeed. Very little help  out there on Stack Overflow. So I'm writing this to help developers who are starting with Oracle APEX.

Use Case : Get selected row(s) from a region such as Interactive Grid/Interactive Report. APEX does not provide a declarative way to perform this operation in Javascript. I tried apex.item(), $v() etc. Nothing seemed to work out.

These are the steps I followed to get the selected selected row from the interactive grid in Oracle APEX.

1. Have a ROW Selector column in the Interactive Grid





2. Create a Dynamic Action in the Grid, with the Event being 'Selection Change [Interactive Grid]'. Now this event is fired each time a selection is changed in the grid. I've disabled multi-select in my grid, but this approach works for multiple selections too.



3. In true action, select 'Execute Javascript Code' and type in the following code


if(this.data != null){
    if(this.data.selectedRecords[0]!= null){
        selectedRecord = this.data.selectedRecords[0][0];
        console.log(selectedRecord);
    }

}




 How did I figure this out? Let's just simple do a console.log(this) on the 'Selection Change' Event.

Here's the screenshot of what is logged on the console.



this.data has selectedRecords, there you go!!! Had some trouble figuring that out! Phew!

Tags : Oracle APEX 5, Oracle APEX5  Interactive Grid selected row javascript, Oracle APEX5 Interactive Grid javascript listener, Oracle APEX5 Region Row Selection, APEX5 region javascript, Oracle APEX5 blog, Oracle APEX5 javascript Interactive grid
 

Creating a headless slave node in Hudson

Generally the Hudson builds are tied up to a slave node. The Slave node can be launched in two ways

        1. As a JNLP client in windows
        2. Via SSH on a Linux machine

Since, the Hudson is generally on Linux Machines, this article focuses on creating a new slave node for Hudson.

1. Navigate to  Hudson home page in your web browser.
2. Click on 'Manage Hudson'.
3. Select 'Managed Nodes'
4. Select 'Create New Node'
5. Provide an appropriate name, click Ok

6. Enter the number of Executors. This is required for the number of concurrent executions to be done
7. Enter the directory where the Hudson Job artifacts should go in
7. In the Launch drop down,
              a. Select Launch Via  Windows slave agent with JNLP
              b. Select Launch Slave via SSH. Click on 'Advanced' to type in additional fields from where the Slave node has to be launched. Type in IP Address, username, password and other fields. Click 'Save'.

Now, the slave node is ready and we can tie up Hudson jobs to this node ;-)







Wednesday 4 December 2013

Resolving UCM Server start issues

The major issues faced while starting up UCM server is related to DB, some f the common checklist items before starting the DB is mentioned below

1. Ensure that Admin Server is running
2. Ensure the UCM DB is up and running. If you're unsure, the DB that UCM is referring can be found by Navigating to Servers -> UCM_server1 -> Monitoring -> JDBC ->CSDS -> Configuration ->ConnectionPool

Here you can view the DB to which the UCM is referring to. To test whether the DB is up and running use
   netstat -plan|grep 1521   . Here the port 1521 is the default DB port, else use the port that is inferred from the CSDS connection pool screen

A common console error can be found below :


<Dec 4, 2013 5:45:06 AM EST> <Error> <ServletContext-> <BEA-000000> <There is aninitialization failure during start up of UCM.>
<Dec 4, 2013 5:45:06 AM EST> <Error> <ServletContext-> <BEA-000000> <Could not start server of type 'server' at default relative web root URL 'cs'.
javax.servlet.ServletException: Could not start up IDC server deployment.
        at idcservlet.ServletUtils.initializeContentServer(ServletUtils.java:1284)
        at idcservlet.ServletUtils.startAndConfigureServer(ServletUtils.java:547)
        at idcservlet.ServletUtils.initializeAllServers(ServletUtils.java:460)
        at idcservlet.IdcFilter.initContentServer(IdcFilter.java:181)
        at idcservlet.IdcFilter.init(IdcFilter.java:156)
        Truncated. see log file for complete stacktrace
Caused By: java.io.IOException: Oracle WebCenter Content failed to initialize inside its servlet environment.
        at intradoc.idcwls.IdcIntegrateWrapper.initializeServer(IdcIntegrateWrapper.java:138)
        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:597)
        Truncated. see log file for complete stacktrace
Caused By: intradoc.common.ServiceException: !csProviderUnableToInitialize,SystemDatabase
        at intradoc.server.IdcSystemLoader.loadProviders(IdcSystemLoader.java:2371)
        at intradoc.server.IdcSystemLoader.initProviders(IdcSystemLoader.java:2124)
        at intradoc.server.IdcSystemLoader.finishInit(IdcSystemLoader.java:400)
        at intradoc.server.IdcSystemLoader.init(IdcSystemLoader.java:335)
        at intradoc.server.IdcServerManager.init(IdcServerManager.java:120)
        Truncated. see log file for complete stacktrace
Caused By: intradoc.data.DataException: !csDbUnableToInitalize,SystemDatabase!csProviderFailedToExtractAndUseDataSource,CSDS
        at intradoc.jdbc.JdbcManager.init(JdbcManager.java:92)
        at intradoc.jdbc.JdbcWorkspace.init(JdbcWorkspace.java:78)
        at intradoc.provider.Provider.init(Provider.java:71)
        at intradoc.server.IdcSystemLoader.loadProviders(IdcSystemLoader.java:2361)
        at intradoc.server.IdcSystemLoader.initProviders(IdcSystemLoader.java:2125)
        Truncated. see log file for complete stacktrace
Caused By: intradoc.data.DataException: !csProviderFailedToExtractAndUseDataSource,CSDS
        at intradoc.provider.ProviderPoolManager.init(ProviderPoolManager.java:134)
        at intradoc.jdbc.JdbcManager.init(JdbcManager.java:79)
        at intradoc.jdbc.JdbcWorkspace.init(JdbcWorkspace.java:82)
        at intradoc.provider.Provider.init(Provider.java:72)
        at intradoc.server.IdcSystemLoader.loadProviders(IdcSystemLoader.java:2361)
        Truncated. see log file for complete stacktrace
Caused By: intradoc.common.ServiceException: !csProviderFailedToAccessDataSource
        at intradoc.provider.ProviderPoolManager.computeExternalConnectionObject(ProviderPoolManager.java:263)
        at intradoc.provider.ProviderPoolManager.init(ProviderPoolManager.java:130)
        at intradoc.jdbc.JdbcManager.init(JdbcManager.java:80)
        at intradoc.jdbc.JdbcWorkspace.init(JdbcWorkspace.java:82)
        at intradoc.provider.Provider.init(Provider.java:72)
        Truncated. see log file for complete stacktrace
Caused By: intradoc.common.ServiceException: !csUnableToExecMethod,getConnection
        at intradoc.common.ClassHelperUtils.convertToStandardException(ClassHelp erUtils.java:202)
        at intradoc.common.ClassHelperUtils.convertToStandardExceptionAndThrow(ClassHelperUtils.java:179)
        at intradoc.common.ClassHelperUtils.executeIdcMethodConvertToStandardExceptions(ClassHelperUtils.java:410)
        at intradoc.provider.ProviderPoolManager.getExternalRawConnection(ProviderPoolManager.java:945)
        at intradoc.provider.ProviderPoolManager.computeExternalConnectionObject(ProviderPoolManager.java:243)
        Truncated. see log file for complete stacktrace
Caused By: weblogic.jdbc.extensions.ConnectionDeadSQLException: weblogic.common.resourcepool.ResourceDeadException: 0:weblogic.common.ResourceException: Could not create pool connection. The DBMS driver exception was: ORA-28001: the password has expired

        at weblogic.jdbc.common.internal.JDBCUtil.wrapAndThrowResourceException(JDBCUtil.java:250)
        at weblogic.jdbc.common.internal.RmiDataSource.getPoolConnection(RmiDataSource.java:456)
        at weblogic.jdbc.common.internal.RmiDataSource.getConnectionInternal(RmiDataSource.java:538)
        at weblogic.jdbc.common.internal.RmiDataSource.getConnection(RmiDataSource.java:498)
        at weblogic.jdbc.common.internal.RmiDataSource.getConnection(RmiDataSource.java:491)
        Truncated. see log file for complete stacktrace
>
<Dec 4, 2013 5:45:06 AM EST> <Notice> <Log Management> <BEA-170027> <The Serverhas established connection with the Domain level Diagnostic Service successfully                                                                                                                     .>
<Dec 4, 2013 5:45:06 AM EST> <Notice> <WebLogicServer> <BEA-000365> <Server state changed to ADMIN>
<Dec 4, 2013 5:45:06 AM EST> <Notice> <WebLogicServer> <BEA-000365> <Server state changed to RESUMING>
<Dec 4, 2013 5:45:06 AM EST> <Notice> <Server> <BEA-002613> <Channel "Default[1]" is now listening on 127.0.0.1:16200 for protocols iiop, t3, ldap, snmp, http.>                                                                                                                    
<Dec 4, 2013 5:45:06 AM EST> <Notice> <Server> <BEA-002613> <Channel "Default" is now listening on 172.10.10.70:16200 for protocols iiop, t3, ldap, snmp, http.>                                                                                                                    
<Dec 4, 2013 5:45:06 AM EST> <Notice> <WebLogicServer> <BEA-000330> <Started Web Logic Managed Server "UCM_server1" for domain "base_domain" running in Production Mode>
<Dec 4, 2013 5:45:21 AM EST> <Warning> <JDBC> <BEA-001129> <Received exception while creating connection for pool "CSDS": ORA-28001: the password has expired
.>
<Dec 4, 2013 5:45:22 AM EST> <Warning> <JDBC> <BEA-001129> <Received exception while creating connection for pool "CSDS": ORA-28001: the password has expired
.>
<Dec 4, 2013 5:45:23 AM EST> <Warning> <JDBC> <BEA-001129> <Received exception while creating connection for pool "CSDS": ORA-28001: the password has expired
<Dec 4, 2013 5:45:36 AM EST> <Notice> <WebLogicServer> <BEA-000365> <Server state changed to RUNNING>
<Dec 4, 2013 5:45:36 AM EST> <Notice> <WebLogicServer> <BEA-000360> <Server started in RUNNING mode>


The Server has already started according to the log!!! Has it really??

If you closely observe the highlighted logs, it says it cant connect to CSDS, the reason is logged as well!!!
In my case the password for DEV_OCS user has expired.  If you try to login into console, you'll get oracle ucm server you'll find this message "The Server is unavailable. Please contact the administrator of this site to report the problem. Click here for server process administration"

Resolving the issue :

1. Login as 'sys' user with SYSDBA role.
2. Expand 'Other users ', you can find 'DEV_OCS'


3. Right Click 'DEV_OCS' ->Edit User
4. Uncheck 'Password Expired'


5. Assign a new password, confirm the password
6. Click on Apply, followed by close
7. After resolving the DB issues (in General), verify whether you can connect to the UCM DB with DEV_OCS user.
8. Once you're able to connect to the DB from DEV_OCS user, then you're good to go.
9. Restart the UCM server and you should be able to access the UCM console via test.example.com:16200/cs

The trick is to make sure DB is up, in running state and accessible as well!!!! 

Sunday 17 November 2013

Getting Selected Row in a Table

Getting the selected Row in the managed bean.

1. The Table in the JSFF looks something like this. The table has a JSFF binding to a bean called "empBackingBean" introduced in the Backing Bean scope in the TF. Lets have an ActionListener in the Managedbean which displays the selected row in the table

<af:table value="#{bindings.VO1.collectionModel}"
                                        var="row"
                                        rows="#{bindings.VO1.rangeSize}"
                                        fetchSize="#{bindings.VO1.rangeSize}"
                                        rowBandingInterval="0"
                                        selectionListener="#{bindings.VO1.collectionModel.makeCurrent}"
                                        rowSelection="single" id="ATt5"
                                        columnStretching="column:c13"
                                        summary="#{myBundle.myTableName}"
                                        displayRow="selected"
                                        binding="#{backingBeanScope.empBackingBean.empTable}">
                                <af:column headerText="c1"
                                           id="c13">
                                   <af:outputText value="#{row.EmpId}"
                                                 id="ot1">
                                </af:column>
 <af:column headerText="c2"
                                           id="c14">
                                     <af:outputText value="#{row.EmpName}"
                                                 id="ot2">
                                </af:column>
<af:commandButton text="showSelectedCustomers 1" id="cb7"  actionListener="pageFlowScope.empManagedBean.showSelectedAL" />


2. The empManagedBean is the java bean that contains 'showSelectedAL'. The method gets the table from which is bound to the backing bean, gets the current row attributes. A custom method to evaluate the EL expression is also a part of the article

 public void showSelectedAL(ActionEvent actionEvent){
      empBackingBean requestBean= (empBackingBean ) evaluateELExp("#{backingBeanScope.empBackingBean }");
        RichTable empTable= requestBean.getEmpTable();
        JUCtrlHierNodeBinding currentEmployee=
            (JUCtrlHierNodeBinding)empTable.getSelectedRowData();
System.out.println("The Selected Employee "+currentEmployee.getAttribute("EmpName"));
// Write your custom logic here
}
public static Object evaluateELExp(String el) {
FacesContext facesContext = FacesContext.getCurrentInstance();
ELContext elContext = facesContext.getELContext();
ExpressionFactory expressionFactory =
facesContext.getApplication().getExpressionFactory();
ValueExpression exp =
expressionFactory.createValueExpression(elContext, el,
Object.class);
return exp.getValue(elContext);
}


This is useful if the row selection is single. Multiple row selection can be handled by using empTable.getSelectedRowKeys(), but it is beyond the scope of this article.