void GroupSynchronizationCallbacks::onFoundGroup(std::shared_ptr<OC::OCResource> groupResource)
{
    LOGI("FindGroup : Enter");

    if (NULL == groupResource.get())
    {
        LOGE("FindGroup : Invalid received GroupResource!");
        return;
    }

    JNIEnv *env = ThingsManagerJVM::getEnv();
    if (env == NULL)
    {
        LOGE("FindGroup : Getting JNIEnv failed");
        return;
    }

    // Get ThingsManagerCallback class reference
    jclass groupSynchronizationCallbacks = GetJClass(TM_SERVICE_GROUP_SYNCHRONIZATION_CLASS_PATH);
    if (NULL == groupSynchronizationCallbacks)
    {
        LOGE("FindGroup : GetJClass TMServiceCallbackInterface failed");
        ThingsManagerJVM::releaseEnv();
        return;
    }

    // Get the ThingsManagerCallback class instance
    jobject jobjectCallback = GetJObjectInstance(TM_SERVICE_GROUP_SYNCHRONIZATION_CLASS_PATH);
    if (NULL == jobjectCallback)
    {
        LOGE("FindGroup: getInstance failed!");
        ThingsManagerJVM::releaseEnv();
        return;
    }

    // Get onGroupFindCallback method reference
    jmethodID method_id = env->GetMethodID(groupSynchronizationCallbacks,
                                           "onGroupFindCallback",
                                           METHOD_ONGROUP_FIND_CALLBACK);
    if (NULL == method_id)
    {
        LOGE("FindGroup : GetMethodID failed");
        ThingsManagerJVM::releaseEnv();
        return;
    }

    if ((env)->ExceptionCheck())
    {
        LOGE("FindGroup : ExceptionCheck failed");
        ThingsManagerJVM::releaseEnv();
        return;
    }

    JniOcResource *jniOcResource = new JniOcResource(groupResource);
    if (!jniOcResource)
    {
        LOGE("FindGroup : groupResource is invalid!");
        ThingsManagerJVM::releaseEnv();
        return;
    }

    jobject resource = OcResourceToJava(env, reinterpret_cast<jlong>(jniOcResource));

    env->CallVoidMethod(jobjectCallback, method_id, resource);

    if ((env)->ExceptionCheck())
    {
        LOGE("FindGroup : CallVoidMethod failed");
        ThingsManagerJVM::releaseEnv();
        return;
    }

    ThingsManagerJVM::releaseEnv();
    LOGI("FindGroup : Exit");
}
void ThingsConfigurationCallbacks::invokeCallback(const OC::HeaderOptions &headerOptions,
        const OC::OCRepresentation &rep, const int eCode, const char  *callbackName,
        const char *signature)
{
    LOGI("InvokeCallback : Enter %s", callbackName);

    JNIEnv *env = ThingsManagerJVM::getEnv();
    if (env == NULL)
    {
        LOGE("InvokeCallback : Getting JNIEnv failed");
        return;
    }

    // Get ThingsManagerCallback class reference
    jclass thingsConfigurationCallbacks = GetJClass(TM_SERVICE_THINGS_CONFIGURATION_CLASS_PATH);
    if (NULL == thingsConfigurationCallbacks)
    {
        LOGE("InvokeCallback : GetJClass TMServiceCallbackInterface failed");
        ThingsManagerJVM::releaseEnv();
        return;
    }

    // Get the ThingsManagerCallback class instance
    jobject jobjectCallback = GetJObjectInstance(TM_SERVICE_THINGS_CONFIGURATION_CLASS_PATH);
    if (NULL == jobjectCallback)
    {
        LOGE("InvokeCallback: getInstance( %s) failed!", TM_SERVICE_THINGS_CONFIGURATION_CLASS_PATH);
        ThingsManagerJVM::releaseEnv();
        return;
    }

    jmethodID method_id = env->GetMethodID(thingsConfigurationCallbacks, callbackName, signature);
    if (!method_id)
    {
        LOGE("InvokeCallback : GetMethodID failed");
        ThingsManagerJVM::releaseEnv();
        return;
    }

    if ((env)->ExceptionCheck())
    {
        LOGE("InvokeCallback : ExceptionCheck failed");
        ThingsManagerJVM::releaseEnv();
        return;
    }

    // Convert vector<OC:HeaderOption::OCHeaderOption> to java type
    jclass vectorCls = env->FindClass(TM_JAVA_VECTOR_CLASS_PATH);
    if (!vectorCls)
    {
        LOGE("InvokeCallback: failed to get %s class reference", TM_JAVA_VECTOR_CLASS_PATH);
        ThingsManagerJVM::releaseEnv();
        return;
    }

    jmethodID constr = env->GetMethodID(vectorCls, "<init>", "()V");
    if (!constr)
    {
        LOGE("InvokeCallback: failed to get %s constructor", TM_JAVA_VECTOR_CLASS_PATH);
        ThingsManagerJVM::releaseEnv();
        return;
    }

    jobject vectorObj = env->NewObject(vectorCls, constr);
    if (!vectorObj)
    {
        LOGE("InvokeCallback: failed to create a %s object", TM_JAVA_VECTOR_CLASS_PATH);
        ThingsManagerJVM::releaseEnv();
        return;
    }

    jmethodID addElement = env->GetMethodID(vectorCls, "addElement", "(Ljava/lang/Object;)V");
    if (NULL == addElement)
    {
        LOGE("InvokeCallback: failed to create a addElement method");
        ThingsManagerJVM::releaseEnv();
        return;
    }

    jobject headerOptionTemp;
    for (int i = 0; i < headerOptions.size(); i++)
    {
        headerOptionTemp = OcHeaderOptionToJava(env, headerOptions[i]);
        env->CallVoidMethod(vectorObj, addElement, headerOptionTemp);
    }

    // Convert OCRepresentation to java type
    jobject jrepresentation = OcRepresentationToJava(env, (jlong) reinterpret_cast<jlong>(&rep));
    if (!jrepresentation)
    {
        LOGE("InvokeCallback : cannot create OCRepresentation class");
        ThingsManagerJVM::releaseEnv();
        return;
    }

    env->CallVoidMethod(jobjectCallback, method_id, vectorObj, jrepresentation, (jint)eCode);

    if ((env)->ExceptionCheck())
    {
        LOGE("InvokeCallback : CallVoidMethod failed");
        ThingsManagerJVM::releaseEnv();
        return;
    }

    ThingsManagerJVM::releaseEnv();
    LOGI("InvokeCallback : Exit %s", callbackName);
}