Merge "Update distribution files to support helm charts"
[music.git] / src / main / java / org / onap / music / rest / RestMusicAdminAPI.java
index c66944c..0e36565 100755 (executable)
@@ -23,10 +23,17 @@ package org.onap.music.rest;
 
 
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
 import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
 import java.util.UUID;
+
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.POST;
@@ -37,21 +44,48 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.ResponseBuilder;
 import javax.ws.rs.core.Response.Status;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.mindrot.jbcrypt.BCrypt;
 import org.onap.music.datastore.PreparedQueryObject;
+import org.onap.music.datastore.jsonobjects.JSONCallbackResponse;
+import org.onap.music.datastore.jsonobjects.JSONObject;
+import org.onap.music.datastore.jsonobjects.JsonCallback;
+import org.onap.music.datastore.jsonobjects.JsonNotification;
+import org.onap.music.datastore.jsonobjects.JsonNotifyClientResponse;
 import org.onap.music.datastore.jsonobjects.JsonOnboard;
 import org.onap.music.eelf.logging.EELFLoggerDelegate;
 import org.onap.music.eelf.logging.format.AppMessages;
 import org.onap.music.eelf.logging.format.ErrorSeverity;
 import org.onap.music.eelf.logging.format.ErrorTypes;
+//import org.onap.music.main.CacheAccess;
 import org.onap.music.main.CachingUtil;
 import org.onap.music.main.MusicCore;
 import org.onap.music.main.MusicUtil;
 import org.onap.music.main.ResultType;
+import org.onap.music.main.ReturnType;
+import org.onap.music.response.jsonobjects.JsonResponse;
+
 import com.datastax.driver.core.DataType;
 import com.datastax.driver.core.ResultSet;
 import com.datastax.driver.core.Row;
+import com.datastax.driver.core.exceptions.InvalidQueryException;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.core.util.Base64;
+
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import com.datastax.driver.core.TableMetadata;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import com.datastax.driver.core.ColumnDefinitions;
+import com.datastax.driver.core.ColumnDefinitions.Definition;
+import com.datastax.driver.core.TableMetadata;
+//import java.util.Base64.Encoder; 
+//import java.util.Base64.Decoder;
 
 @Path("/v2/admin")
 // @Path("/v{version: [0-9]+}/admin")
@@ -60,7 +94,6 @@ import io.swagger.annotations.ApiOperation;
 public class RestMusicAdminAPI {
     private static EELFLoggerDelegate logger =
                     EELFLoggerDelegate.getLogger(RestMusicAdminAPI.class);
-
     /*
      * API to onboard an application with MUSIC. This is the mandatory first step.
      * 
@@ -107,7 +140,7 @@ public class RestMusicAdminAPI {
                         MusicUtil.DEFAULTKEYSPACENAME));
         pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName));
         pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True"));
-        pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), password));
+        pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), BCrypt.hashpw(password, BCrypt.gensalt())));
         pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId));
         pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF));
 
@@ -142,7 +175,7 @@ public class RestMusicAdminAPI {
                             ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
             resultMap.put("Exception",
                             "Unauthorized: Please check the request parameters. Enter atleast one of the following parameters: appName(ns), aid, isAAF.");
-            return Response.status(Status.UNAUTHORIZED).entity(resultMap).build();
+            return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
         }
 
         PreparedQueryObject pQuery = new PreparedQueryObject();
@@ -156,9 +189,8 @@ public class RestMusicAdminAPI {
 
         if (cql.endsWith("AND "))
             cql = cql.trim().substring(0, cql.length() - 4);
-        System.out.println("Query is: " + cql);
+        logger.info("Query in callback is: " + cql);
         cql = cql + " allow filtering";
-        System.out.println("Get OnboardingInfo CQL: " + cql);
         pQuery.appendQueryString(cql);
         if (appName != null)
             pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName));
@@ -348,7 +380,7 @@ public class RestMusicAdminAPI {
         if (userId != null)
             pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId));
         if (password != null)
-            pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), password));
+            pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), BCrypt.hashpw(password, BCrypt.gensalt())));
         if (isAAF != null)
             pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF));
 
@@ -367,4 +399,447 @@ public class RestMusicAdminAPI {
 
         return Response.status(Status.OK).entity(resultMap).build();
     }
+
+    Client client = Client.create();
+       ObjectMapper mapper = new ObjectMapper();
+       
+    @POST
+    @Path("/callbackOps")
+    @Produces(MediaType.APPLICATION_JSON)
+    @Consumes(MediaType.APPLICATION_JSON)
+       public Response callbackOps(final JSONObject inputJsonObj) {
+         // {"keyspace":"conductor","full_table":"conductor.plans","changeValue":{"conductor.plans.status":"Who??","position":"3"},"operation":"update","table_name":"plans","primary_key":"3"}
+       Map<String, Object> resultMap = new HashMap<>();
+       new Thread(new Runnable() {
+           public void run() {
+               makeAsyncCall(inputJsonObj);
+           }
+       }).start();
+           
+               return Response.status(Status.OK).entity(resultMap).build();
+       }
+    
+    private Response makeAsyncCall(JSONObject inputJsonObj) {
+       
+       Map<String, Object> resultMap = new HashMap<>();
+       try {
+               logger.info(EELFLoggerDelegate.applicationLogger, "Got notification: " + inputJsonObj.getData());
+                       String dataStr = inputJsonObj.getData();
+                       JSONCallbackResponse jsonResponse = mapper.readValue(dataStr, JSONCallbackResponse.class);
+                       String operation = jsonResponse.getOperation();
+                       Map<String, String> changeValueMap = jsonResponse.getChangeValue();
+                       String primaryKey = jsonResponse.getPrimary_key();
+                       String ksTableName = jsonResponse.getFull_table(); //conductor.plans
+                       if(ksTableName.equals("admin.notification_master")) {
+                               CachingUtil.updateCallbackNotifyList(new ArrayList<String>());
+                               return Response.status(Status.OK).entity(resultMap).build();
+                       }
+                       List<String> inputUpdateList = jsonResponse.getUpdateList();
+                       /*String field_value = changeValueMap.get("field_value");
+                       if(field_value == null)
+                               field_value = jsonResponse.getFull_table();*/
+                       String field_value = null;
+                       List<String> notifiyList = CachingUtil.getCallbackNotifyList();
+                       if(notifiyList == null || notifiyList.isEmpty()) {
+                               logger.info("Is cache empty? reconstructing Object from cache..");
+                               constructJsonCallbackFromCache();
+                               /*notifiyList = CachingUtil.getCallbackNotifyList();
+                               if("update".equals(operation)) {
+                                       List<String> updateList = jsonResponse.getUpdateList();
+                                       //logger.info("update list from trigger: "+updateList);
+                                       for(String element : updateList) {
+                                               logger.info("element: "+element);
+                                               logger.info("notifiyList: "+notifiyList);
+                                               if(notifiyList.contains(element)) {
+                                                       logger.info("Found the notifyOn property: "+element);
+                                                       field_value = element;
+                                               }
+                                       }
+                               }
+                               
+                               baseRequestObj = CachingUtil.getCallBackCache(field_value);
+                               logger.info("Reconstructing Object from cache is Successful.."+baseRequestObj);*/
+                       }
+                       notifiyList = CachingUtil.getCallbackNotifyList();
+                       JsonCallback baseRequestObj = null;
+                       
+                       if("update".equals(operation)) {
+                               for(String element: inputUpdateList) {
+                                       baseRequestObj = CachingUtil.getCallBackCache(element);
+                                       if(baseRequestObj != null) {
+                                               logger.info("Found the element that was changed... "+element);
+                                               break;
+                                       }
+                               }
+                               
+                               List<String> updateList = jsonResponse.getUpdateList();
+                               //logger.info("update list from trigger: "+updateList);
+                               for(String element : updateList) {
+                                       if(notifiyList.contains(element)) {
+                                               logger.info("Found the notifyOn property: "+element);
+                                               field_value = element;
+                                               break;
+                                       }
+                               }
+                               if(baseRequestObj == null || field_value == null) {
+                                       for(String element: inputUpdateList) {
+                                               String[] elementArr = element.split(":");
+                                               String newElement = null;
+                                               if(elementArr.length >= 2) {
+                                                       newElement = elementArr[0]+":"+elementArr[1];
+                                       } 
+                                               baseRequestObj = CachingUtil.getCallBackCache(newElement);
+                                               if(baseRequestObj != null) {
+                                                       logger.info("Found the element that was changed... "+newElement);
+                                                       break;
+                                               }
+                                       }
+                                       for(String element : updateList) {
+                                               String[] elementArr = element.split(":");
+                                               String newElement = null;
+                                               if(elementArr.length >= 2) {
+                                                       newElement = elementArr[0]+":"+elementArr[1];
+                                       } 
+                                               if(notifiyList.contains(newElement)) {
+                                                       logger.info("Found the notifyOn property: "+newElement);
+                                                       field_value = newElement;
+                                                       break;
+                                               }
+                                       }
+                               }
+                       } else {
+                               field_value = jsonResponse.getFull_table();
+                               baseRequestObj = CachingUtil.getCallBackCache(field_value);
+                       }
+                       
+                       if(baseRequestObj == null) {
+                               resultMap.put("Exception",
+                           "Oops. Something went wrong. Please make sure Callback properties are onboarded.");
+                               logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.INCORRECTDATA,
+                           ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
+                               return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
+                       }
+                       logger.info("Going through list: "+operation+ " && List: "+jsonResponse.getUpdateList());
+                       
+                       String key = "admin" + "." + "notification_master" + "." + baseRequestObj.getUuid();
+               String lockId = MusicCore.createLockReference(key);
+               ReturnType lockAcqResult = MusicCore.acquireLock(key, lockId);
+               if(! lockAcqResult.getResult().toString().equals("SUCCESS")) {
+                       logger.error(EELFLoggerDelegate.errorLogger, "Some other node is notifying the caller..: ");
+               }
+                       
+                       logger.info(operation+ ": Operation :: changeValue: "+changeValueMap);
+                       if(operation.equals("update")) {
+                               String notifyWhenChangeIn = baseRequestObj.getNotifyWhenChangeIn(); // conductor.plans.status
+                               if(null!=field_value) {
+                                       if(field_value.equals(notifyWhenChangeIn)) {
+                                               notifyCallBackAppl(jsonResponse, baseRequestObj);
+                                       }
+                               }
+                       } else if(operation.equals("delete")) {
+                               String notifyWhenDeletesIn = baseRequestObj.getNotifyWhenDeletesIn(); // conductor.plans.status
+                               if(null!=field_value) {
+                                       if(field_value.equals(notifyWhenDeletesIn)) {
+                                               notifyCallBackAppl(jsonResponse, baseRequestObj);
+                                       }
+                               }
+                       } else if(operation.equals("insert")) {
+                               String notifyWhenInsertsIn = baseRequestObj.getNotifyWhenInsertsIn(); // conductor.plans.status
+                               if(null!=field_value) {
+                                       if(field_value.equals(notifyWhenInsertsIn)) {
+                                               notifyCallBackAppl(jsonResponse, baseRequestObj);
+                                       }
+                               }
+                       }
+                       MusicCore.releaseLock(lockId, true);    
+           } catch(Exception e) {
+            e.printStackTrace();
+            logger.info("Exception...");
+        }
+       logger.info(EELFLoggerDelegate.applicationLogger, "callback is completed. Notification was sent from Music...");
+       return Response.status(Status.OK).entity(resultMap).build();
+    }
+    
+    private void notifyCallBackAppl(JSONCallbackResponse jsonResponse, JsonCallback baseRequestObj) {
+       int notifytimeout = MusicUtil.getNotifyTimeout();
+       int notifyinterval = MusicUtil.getNotifyInterval();
+       String endpoint = baseRequestObj.getApplicationNotificationEndpoint();
+        String username = baseRequestObj.getApplicationUsername();
+        String password = baseRequestObj.getApplicationPassword();
+        JsonNotification jsonNotification = constructJsonNotification(jsonResponse, baseRequestObj);
+        jsonNotification.setOperation_type(jsonResponse.getOperation());
+        logger.info(EELFLoggerDelegate.applicationLogger, "Notification Response sent is: "+jsonNotification);
+        WebResource webResource = client.resource(endpoint);
+        String authData = username+":"+password;
+        byte[] plainCredsBytes = authData.getBytes();
+        byte[] base64CredsBytes = Base64.encode(plainCredsBytes);
+        String base64Creds = new String(base64CredsBytes);
+        Map<String, String> response_body = baseRequestObj.getResponseBody();
+        ClientResponse response = null;
+        try { 
+               response = webResource.header("Authorization", "Basic " + base64Creds).accept("application/json").type("application/json")
+            .post(ClientResponse.class, jsonNotification);
+        } catch (com.sun.jersey.api.client.ClientHandlerException chf) {
+               boolean ok = false;
+               logger.info(EELFLoggerDelegate.applicationLogger, "Is Service down?");
+               long now= System.currentTimeMillis();
+               long end = now+notifytimeout;
+               while(! ok) {
+                       logger.info(EELFLoggerDelegate.applicationLogger, "retrying since error in notifying callback..");
+                       try {
+                               response = webResource.header("Authorization", "Basic " + base64Creds).accept("application/json").type("application/json")
+                           .post(ClientResponse.class, jsonNotification);
+                               if(response.getStatus() == 200) ok = true;
+                       }catch (Exception e) {
+                               logger.info(EELFLoggerDelegate.applicationLogger, "Retry until "+(end-System.currentTimeMillis()));
+                               if(response == null && System.currentTimeMillis() < end) ok = false;
+                               else ok = true;
+                               try{ Thread.sleep(notifyinterval); } catch(Exception e1) {}
+                       }
+               }
+        }
+        if(response == null) {
+               logger.error(EELFLoggerDelegate.errorLogger, "Can NOT notify the caller as caller failed to respond..");
+               return;
+        }
+        JsonNotifyClientResponse responseStr = response.getEntity(JsonNotifyClientResponse.class);
+        logger.info(EELFLoggerDelegate.applicationLogger, "Response from Notified client: "+responseStr);
+        
+        if(response.getStatus() != 200){
+               long now= System.currentTimeMillis();
+               long end = now+30000;
+               while(response.getStatus() != 200 && System.currentTimeMillis() < end) {
+                       logger.info(EELFLoggerDelegate.applicationLogger, "retrying since error in notifying callback..");
+                       response = webResource.header("Authorization", "Basic " + base64Creds).accept("application/json").type("application/json")
+                           .post(ClientResponse.class, jsonNotification);
+               }
+               logger.info(EELFLoggerDelegate.applicationLogger, "Exception while notifying.. "+response.getStatus());
+        }
+    }
+    
+    private JsonNotification constructJsonNotification(JSONCallbackResponse jsonResponse, JsonCallback baseRequestObj) {
+       
+       JsonNotification jsonNotification = new JsonNotification();
+       try {
+               jsonNotification.setNotify_field(baseRequestObj.getNotifyOn());
+               jsonNotification.setEndpoint(baseRequestObj.getApplicationNotificationEndpoint());
+               jsonNotification.setUsername(baseRequestObj.getApplicationUsername());
+               jsonNotification.setPassword(baseRequestObj.getApplicationPassword());
+               String pkValue = jsonResponse.getPrimary_key();
+               
+               String[] fullNotifyArr = baseRequestObj.getNotifyOn().split(":");
+               
+               String[] tableArr = fullNotifyArr[0].split("\\.");
+               TableMetadata tableInfo = MusicCore.returnColumnMetadata(tableArr[0], tableArr[1]);
+                       DataType primaryIdType = tableInfo.getPrimaryKey().get(0).getType();
+                       String primaryId = tableInfo.getPrimaryKey().get(0).getName();
+                       
+                       Map<String, String> responseBodyMap = baseRequestObj.getResponseBody();
+                       Map<String, String> newMap = new HashMap<>();
+                       if(responseBodyMap.size() == 1 && responseBodyMap.containsKey("")) {
+                               jsonNotification.setResponse_body(newMap);
+                       } else {
+                               for (Entry<String, String> entry : new HashSet<>(responseBodyMap.entrySet())) {
+                                   String trimmed = entry.getKey().trim();
+                                   if (!trimmed.equals(entry.getKey())) {
+                                       responseBodyMap.remove(entry.getKey());
+                                       responseBodyMap.put(trimmed, entry.getValue());
+                                   }
+                               }
+                               
+                               Set<String> keySet = responseBodyMap.keySet();
+                               String cql = "select *";
+                               /*for(String keys: keySet) {
+                                       cql = cql + keys + ",";
+                               }*/
+                               //cql = cql.substring(0, cql.length()-1);
+                               cql = cql + " FROM "+fullNotifyArr[0]+" WHERE "+primaryId+" = ?";
+                               logger.info("CQL in constructJsonNotification: "+cql);
+                               PreparedQueryObject pQuery = new PreparedQueryObject();
+                               pQuery.appendQueryString(cql);
+                               pQuery.addValue(MusicUtil.convertToActualDataType(primaryIdType, pkValue));
+                               Row row = MusicCore.get(pQuery).one();
+                               if(row != null) {
+                                       ColumnDefinitions colInfo = row.getColumnDefinitions();
+                               for (Definition definition : colInfo) {
+                                   String colName = definition.getName();
+                                   if(keySet.contains(colName)) {
+                                       DataType colType = definition.getType();
+                                       Object valueObj = MusicCore.getDSHandle().getColValue(row, colName, colType);
+                                       Object valueString = MusicUtil.convertToActualDataType(colType, valueObj);
+                                       logger.info(colName+" : "+valueString);
+                                       newMap.put(colName, valueString.toString());
+                                       keySet.remove(colName);
+                                   }
+                               }
+                               }
+                               if(! keySet.isEmpty()) {
+                                       Iterator<String> iterator = keySet.iterator();
+                                       while (iterator.hasNext()) {
+                                           String element = iterator.next();
+                                           if(element != null && element.length() > 0)
+                                               newMap.put(element,"COLUMN_NOT_FOUND");
+                                       }
+                               }
+                           
+                               if("delete".equals(jsonResponse.getOperation()) || newMap.isEmpty()) {
+                                       newMap.put(primaryId, pkValue);
+                               }
+                               jsonNotification.setResponse_body(newMap);
+                       }
+                       } catch(Exception e) {
+                       e.printStackTrace();
+                       }
+                       return jsonNotification;
+    }
+    
+    private void constructJsonCallbackFromCache() throws Exception{
+       PreparedQueryObject pQuery = new PreparedQueryObject();
+               JsonCallback jsonCallback = null;
+               List<String> notifyList = new java.util.ArrayList<>();
+               String cql = 
+                "select id, endpoint_userid, endpoint_password, notify_to_endpoint, notify_insert_on,"
+                + " notify_delete_on, notify_update_on, request, notifyon from admin.notification_master allow filtering";
+        pQuery.appendQueryString(cql);
+        //pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), fullTable));
+        logger.info("Query: "+pQuery.getQuery());
+        
+        ResultSet rs = MusicCore.get(pQuery);
+        Iterator<Row> it = rs.iterator();
+        while (it.hasNext()) {
+            Row row = (Row) it.next();
+               String endpoint = row.getString("notify_to_endpoint");
+            String username = row.getString("endpoint_userid");
+            ByteBuffer passwordBytes = row.getBytes("endpoint_password");
+            String insert = row.getString("notify_insert_on");
+            String delete = row.getString("notify_delete_on");
+            String update = row.getString("notify_update_on");
+            String request = row.getString("request");
+            String notifyon = row.getString("notifyon");
+            String uuid = row.getUUID("id").toString();
+            notifyList.add(notifyon);
+            jsonCallback = new JsonCallback();
+            jsonCallback.setApplicationNotificationEndpoint(endpoint);
+            
+            Charset charset = Charset.forName("ISO-8859-1");
+            String decodedPwd = charset.decode(passwordBytes).toString();
+            jsonCallback.setApplicationPassword(decodedPwd);
+            jsonCallback.setApplicationUsername(username);
+            jsonCallback.setNotifyOn(notifyon);
+            jsonCallback.setNotifyWhenInsertsIn(insert);
+            jsonCallback.setNotifyWhenDeletesIn(delete);
+            jsonCallback.setNotifyWhenChangeIn(update);
+            jsonCallback.setUuid(uuid);
+            logger.info("From DB. Saved request_body: "+request);
+            request = request.substring(1, request.length()-1);           
+            String[] keyValuePairs = request.split(",");              
+            Map<String,String> responseBody = new HashMap<>();               
+
+            for(String pair : keyValuePairs) {
+                String[] entry = pair.split("="); 
+                String val = "";
+                if(entry.length == 2)
+                       val = entry[1];
+                responseBody.put(entry[0], val);          
+            }
+            logger.info("After parsing. Saved request_body: "+responseBody);
+            jsonCallback.setResponseBody(responseBody);
+            logger.info("Updating Cache with updateCallBackCache: "+notifyon+ " :::: "+jsonCallback);
+            CachingUtil.updateCallBackCache(notifyon, jsonCallback);
+        }
+        CachingUtil.updateCallbackNotifyList(notifyList);
+    }
+    
+    @POST
+    @Path("/onboardCallback")
+    @Produces(MediaType.APPLICATION_JSON)
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response addCallback(JsonNotification jsonNotification) {
+        Map<String, Object> resultMap = new HashMap<>();
+        ResponseBuilder response =
+                        Response.noContent().header("X-latestVersion", MusicUtil.getVersion());
+        String username = jsonNotification.getUsername();
+        String password = jsonNotification.getPassword();
+        String endpoint = jsonNotification.getEndpoint();
+        String notify_field = jsonNotification.getNotify_field();
+        Map<String, String> responseBody = jsonNotification.getResponse_body();
+        String triggerName = jsonNotification.getTriggerName();
+        if(triggerName == null || triggerName.length() == 0)
+               triggerName = "MusicTrigger";
+        
+        /*JsonCallback callBackCache = CachingUtil.getCallBackCache(notify_field);
+        if(callBackCache != null) {
+               resultMap.put("Exception", "The notification property has already been onboarded.");
+            return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
+        }*/
+        
+        String[] allFields = notify_field.split(":");
+        String inserts = null;
+        String updates = null;
+        String deletes = null;
+        String tableName = null;
+        if(allFields.length >= 2) {
+               inserts = updates = notify_field;
+        } else if(allFields.length == 1) {
+               inserts = deletes = notify_field;;
+        }
+        tableName = allFields[0];
+        String cql = "CREATE TRIGGER IF NOT EXISTS musictrigger ON "+tableName+" Using '"+triggerName+"'";
+        PreparedQueryObject pQuery = new PreparedQueryObject();
+        
+        String uuid = CachingUtil.generateUUID();
+        try {
+               pQuery.appendQueryString(
+                               "INSERT INTO admin.notification_master (id, endpoint_userid, endpoint_password, notify_to_endpoint, "
+                                               + "notifyon, notify_insert_on, notify_delete_on, notify_update_on, request, current_notifier) VALUES (?,?,?,?,?,?,?,?,?,?)");
+               pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid));
+               pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), username));
+               Charset charset = Charset.forName("ISO-8859-1");
+            ByteBuffer decodedPwd = charset.encode(password); 
+               pQuery.addValue(MusicUtil.convertToActualDataType(DataType.blob(), decodedPwd.array()));
+               pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), endpoint));
+               pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), notify_field));
+               pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), inserts));
+               pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), deletes));
+               pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), updates));
+               pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), responseBody));
+               pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), MusicCore.getMyHostId()));
+               MusicCore.nonKeyRelatedPut(pQuery, MusicUtil.EVENTUAL);
+               JsonCallback jsonCallback = new JsonCallback();
+               jsonCallback.setUuid(uuid);
+               jsonCallback.setApplicationNotificationEndpoint(endpoint);
+               jsonCallback.setApplicationPassword(password);
+               jsonCallback.setApplicationUsername(username);
+               jsonCallback.setNotifyOn(notify_field);
+               jsonCallback.setNotifyWhenChangeIn(updates);
+               jsonCallback.setNotifyWhenDeletesIn(deletes);
+               jsonCallback.setNotifyWhenInsertsIn(inserts);
+               jsonCallback.setResponseBody(responseBody);
+               CachingUtil.updateCallBackCache(notify_field, jsonCallback);
+               logger.info("Cache updated ");
+               pQuery = new PreparedQueryObject();
+               pQuery.appendQueryString(cql);
+               ResultType nonKeyRelatedPut = MusicCore.nonKeyRelatedPut(pQuery, MusicUtil.EVENTUAL);
+               logger.info(EELFLoggerDelegate.applicationLogger, "Created trigger");
+        //callBackCache.put(jsonCallback.getApplicationName(), jsonMap);
+        } catch (InvalidQueryException e) {
+            logger.error(EELFLoggerDelegate.errorLogger,"Exception callback_api table not configured."+e.getMessage());
+            resultMap.put("Exception", "Please make sure admin.notification_master table is configured.");
+            return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
+        } catch(Exception e) {
+               e.printStackTrace();
+               resultMap.put("Exception", "Exception Occured.");
+            return Response.status(Status.BAD_REQUEST).entity(resultMap).build();
+        }
+       return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Callback api successfully registered").toMap()).build();
+    }
+
+    /*public String encodePwd(String password) {
+       return Base64.getEncoder().encodeToString(password.getBytes());
+    }
+    
+    public String decodePwd(String password) {
+       byte[] bytes = Base64.getDecoder().decode(password); 
+       return new String(bytes);
+    }*/
 }