From 42bb61fd162b3dd469c9d98a9dc6d3e2b2eaffce Mon Sep 17 00:00:00 2001 From: Tibor Sirovatka Date: Wed, 18 May 2016 14:54:50 +0200 Subject: [PATCH] HONEYCOMB-67 Introduce exception handling into JVPP Send calls throws VppInvocationException on failure Failed requests (negative retval) reported over onError callback interface method Removed retval attributes from dto/xxxReply.java calls Change-Id: Ibd4e90c320d080e02d75b4bd056a7b11c8e37aa7 Signed-off-by: Tibor Sirovatka --- vpp-api/java/japi/vppjni.c | 4 ++ vpp-api/java/jvpp/gen/dto_gen.py | 8 ++- vpp-api/java/jvpp/gen/jvpp_c_gen.py | 56 ++++++++++++++-- vpp-api/java/jvpp/gen/jvpp_callback_facade_gen.py | 30 +++++++-- vpp-api/java/jvpp/gen/jvpp_future_facade_gen.py | 31 +++++---- vpp-api/java/jvpp/gen/jvpp_impl_gen.py | 32 ++++++---- vpp-api/java/jvpp/gen/util.py | 3 + vpp-api/java/jvpp/jvpp.c | 67 ++++++++++++++++---- .../org/openvpp/jvpp/VppBaseCallException.java | 60 ++++++++++++++++++ .../org/openvpp/jvpp/VppCallbackException.java | 47 ++++++++++++++ .../org/openvpp/jvpp/VppInvocationException.java | 33 ++++++++++ .../org/openvpp/jvpp/callback/JVppCallback.java | 10 ++- .../jvpp/org/openvpp/jvpp/dto/JVppRequest.java | 3 +- .../org/openvpp/jvpp/future/FutureJVppInvoker.java | 4 +- .../jvpp/future/FutureJVppInvokerFacade.java | 42 ++++++------ .../org/openvpp/jvpp/test/CallbackApiTest.java | 27 ++++---- .../openvpp/jvpp/test/CallbackJVppFacadeTest.java | 60 +++++++++++++++--- .../org/openvpp/jvpp/test/ControlPingTest.java | 11 +++- .../openvpp/jvpp/test/CreateSubInterfaceTest.java | 7 +- .../jvpp/org/openvpp/jvpp/test/FutureApiTest.java | 31 ++++----- .../java/jvpp/org/openvpp/jvpp/test/L2AclTest.java | 13 ++-- .../org/openvpp/jvpp/test/OnErrorCallbackTest.java | 74 ++++++++++++++++++++++ vpp-api/java/jvpp/org/openvpp/jvpp/test/Readme.txt | 3 +- 23 files changed, 529 insertions(+), 127 deletions(-) create mode 100644 vpp-api/java/jvpp/org/openvpp/jvpp/VppBaseCallException.java create mode 100644 vpp-api/java/jvpp/org/openvpp/jvpp/VppCallbackException.java create mode 100644 vpp-api/java/jvpp/org/openvpp/jvpp/VppInvocationException.java create mode 100644 vpp-api/java/jvpp/org/openvpp/jvpp/test/OnErrorCallbackTest.java diff --git a/vpp-api/java/japi/vppjni.c b/vpp-api/java/japi/vppjni.c index 5645263aef8..f1b8eda110f 100644 --- a/vpp-api/java/japi/vppjni.c +++ b/vpp-api/java/japi/vppjni.c @@ -41,7 +41,9 @@ #include #undef vl_printfun +#ifndef VPPJNI_DEBUG #define VPPJNI_DEBUG 0 +#endif #if VPPJNI_DEBUG == 1 #define DEBUG_LOG(...) clib_warning(__VA_ARGS__) @@ -1683,7 +1685,9 @@ out: jm->result_ready = 1; } +#ifndef VPPJNI_DEBUG_COUNTERS #define VPPJNI_DEBUG_COUNTERS 0 +#endif static void vl_api_vnet_interface_counters_t_handler (vl_api_vnet_interface_counters_t *mp) diff --git a/vpp-api/java/jvpp/gen/dto_gen.py b/vpp-api/java/jvpp/gen/dto_gen.py index 378d279c6d0..05859dbe83a 100644 --- a/vpp-api/java/jvpp/gen/dto_gen.py +++ b/vpp-api/java/jvpp/gen/dto_gen.py @@ -36,7 +36,7 @@ $methods field_template = Template(""" public $type $name;\n""") send_template = Template(""" @Override - public int send(final $base_package.JVpp jvpp) { + public int send(final $base_package.JVpp jvpp) throws org.openvpp.jvpp.VppInvocationException { return jvpp.$method_name($args); }\n""") @@ -58,8 +58,12 @@ def generate_dtos(func_list, base_package, dto_package, inputfile): fields = "" for t in zip(func['types'], func['args']): + # for retval don't generate dto field in Reply + field_name = util.underscore_to_camelcase(t[1]) + if util.is_reply(camel_case_dto_name) and util.is_retval_field(field_name): + continue fields += field_template.substitute(type=util.jni_2_java_type_mapping[t[0]], - name=util.underscore_to_camelcase(t[1])) + name=field_name) methods = "" base_type = "" if util.is_reply(camel_case_dto_name): diff --git a/vpp-api/java/jvpp/gen/jvpp_c_gen.py b/vpp-api/java/jvpp/gen/jvpp_c_gen.py index a92dd69c853..082fd5d73ae 100644 --- a/vpp-api/java/jvpp/gen/jvpp_c_gen.py +++ b/vpp-api/java/jvpp/gen/jvpp_c_gen.py @@ -31,6 +31,13 @@ find_class_invocation_template = Template(""" return JNI_ERR; }""") +find_class_template = Template(""" + ${ref_name}Class = (jclass)(*env)->NewGlobalRef(env, (*env)->FindClass(env, "${class_name}")); + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionDescribe(env); + return JNI_ERR; + }""") + class_cache_template = Template(""" $class_references static int cache_class_references(JNIEnv* env) { @@ -57,6 +64,14 @@ def generate_class_cache(func_list): ref_name=ref_name, class_name=class_name)) + # add exception class to class cache + ref_name = 'callbackException' + class_name = 'org/openvpp/jvpp/VppCallbackException' + class_references.append(class_reference_template.substitute( + ref_name=ref_name)) + find_class_invocations.append(find_class_template.substitute( + ref_name=ref_name, + class_name=class_name)) return class_cache_template.substitute( class_references="".join(class_references), find_class_invocations="".join(find_class_invocations)) @@ -147,6 +162,9 @@ JNIEXPORT jint JNICALL Java_org_openvpp_jvpp_JVppImpl_${java_name}0 mp->context = clib_host_to_net_u32 (my_context_id); $struct_setters S; + if ((*env)->ExceptionCheck(env)) { + return JNI_ERR; + } return my_context_id; }""") @@ -273,6 +291,19 @@ dto_field_setter_templates = {'u8': default_dto_field_setter_template, 'u64[]': u64_array_dto_field_setter_template } +# code fragment for checking result of the operation before sending request reply +callback_err_handler_template = Template(""" + // for negative result don't send callback message but send error callback + if (mp->retval<0) { + CallOnError("${handler_name}",mp->context,mp->retval); + return; + } + if (mp->retval == VNET_API_ERROR_IN_PROGRESS) { + clib_warning("Result in progress"); + return; + } +""") + msg_handler_template = Template(""" /** * Handler for ${handler_name} vpe.api message. @@ -283,6 +314,7 @@ static void vl_api_${handler_name}_t_handler (vl_api_${handler_name}_t * mp) { vppjni_main_t * jm = &vppjni_main; JNIEnv *env = jm->jenv; + $err_handler jmethodID constructor = (*env)->GetMethodID(env, ${class_ref_name}Class, "", "()V"); jmethodID callbackMethod = (*env)->GetMethodID(env, jm->callbackClass, "on${dto_name}", "(Lorg/openvpp/jvpp/dto/${dto_name};)V"); @@ -304,6 +336,7 @@ def generate_msg_handlers(func_list, inputfile): continue dto_setters = '' + err_handler = '' # dto setters for t in zip(f['c_types'], f['types'], f['args'], f['lengths']): c_type = t[0] @@ -311,6 +344,13 @@ def generate_msg_handlers(func_list, inputfile): c_name = t[2] field_length = t[3] + # for retval don't generate setters and generate retval check + if util.is_retval_field(c_name): + err_handler = callback_err_handler_template.substitute( + handler_name=handler_name + ) + continue + java_field_name = util.underscore_to_camelcase(c_name) jni_signature = util.jni_2_signature_mapping[jni_type] jni_setter = util.jni_field_accessors[jni_type] @@ -330,12 +370,13 @@ def generate_msg_handlers(func_list, inputfile): field_length=field_length) handlers.append(msg_handler_template.substitute( - inputfile=inputfile, - api_data=util.api_message_to_javadoc(f), - handler_name=handler_name, - dto_name=dto_name, - class_ref_name=ref_name, - dto_setters=dto_setters)) + inputfile=inputfile, + api_data=util.api_message_to_javadoc(f), + handler_name=handler_name, + dto_name=dto_name, + class_ref_name=ref_name, + dto_setters=dto_setters, + err_handler=err_handler)) return "\n".join(handlers) @@ -367,6 +408,8 @@ jvpp_c_template = Template("""/** * (python representation of vpe.api generated by vppapigen). */ +void CallOnError(const char* call, int context, int retval); + // JAVA class reference cache $class_cache @@ -399,4 +442,3 @@ def generate_jvpp(func_list, inputfile): jvpp_c_file.flush() jvpp_c_file.close() - diff --git a/vpp-api/java/jvpp/gen/jvpp_callback_facade_gen.py b/vpp-api/java/jvpp/gen/jvpp_callback_facade_gen.py index e8de3fc10c1..acf29eb85b8 100644 --- a/vpp-api/java/jvpp/gen/jvpp_callback_facade_gen.py +++ b/vpp-api/java/jvpp/gen/jvpp_callback_facade_gen.py @@ -77,16 +77,17 @@ $methods """) method_template = Template( - """ void $name($base_package.$dto_package.$request request, $base_package.$callback_package.$callback callback);""") -method_impl_template = Template(""" public final void $name($base_package.$dto_package.$request request, $base_package.$callback_package.$callback callback) { + """ void $name($base_package.$dto_package.$request request, $base_package.$callback_package.$callback callback) throws org.openvpp.jvpp.VppInvocationException;""") + +method_impl_template = Template(""" public final void $name($base_package.$dto_package.$request request, $base_package.$callback_package.$callback callback) throws org.openvpp.jvpp.VppInvocationException { synchronized (callbacks) { callbacks.put(jvpp.$name(request), callback); } } """) -no_arg_method_template = Template(""" void $name($base_package.$callback_package.$callback callback);""") -no_arg_method_impl_template = Template(""" public final void $name($base_package.$callback_package.$callback callback) { +no_arg_method_template = Template(""" void $name($base_package.$callback_package.$callback callback) throws org.openvpp.jvpp.VppInvocationException;""") +no_arg_method_impl_template = Template(""" public final void $name($base_package.$callback_package.$callback callback) throws org.openvpp.jvpp.VppInvocationException { synchronized (callbacks) { callbacks.put(jvpp.$name(), callback); } @@ -172,18 +173,37 @@ jvpp_facade_callback_template = Template(""" package $base_package.$callback_facade_package; /** - *

JVppGlobalCallback implementation for Java Callback API. + *

Implementation of JVppGlobalCallback interface for Java Callback API. *
It was generated by jvpp_callback_facade_gen.py based on $inputfile *
(python representation of vpe.api generated by vppapigen). */ public final class CallbackJVppFacadeCallback implements $base_package.$callback_package.JVppGlobalCallback { private final java.util.Map requests; + private static final java.util.logging.Logger LOG = java.util.logging.Logger.getLogger(CallbackJVppFacadeCallback.class.getName()); public CallbackJVppFacadeCallback(final java.util.Map requestMap) { this.requests = requestMap; } + @Override + public void onError(org.openvpp.jvpp.VppCallbackException reply) { + + $base_package.$callback_package.JVppCallback failedCall; + synchronized(requests) { + failedCall = requests.remove(reply.getCtxId()); + } + + if(failedCall != null) { + try { + failedCall.onError(reply); + } catch(RuntimeException ex) { + ex.addSuppressed(reply); + LOG.log(java.util.logging.Level.WARNING, String.format("Callback: %s failed while handling exception: %s", failedCall, reply), ex); + } + } + } + $methods } """) diff --git a/vpp-api/java/jvpp/gen/jvpp_future_facade_gen.py b/vpp-api/java/jvpp/gen/jvpp_future_facade_gen.py index 5574f120712..7a5a166733c 100644 --- a/vpp-api/java/jvpp/gen/jvpp_future_facade_gen.py +++ b/vpp-api/java/jvpp/gen/jvpp_future_facade_gen.py @@ -35,6 +35,23 @@ public final class FutureJVppFacadeCallback implements $base_package.$callback_p this.requests = requestMap; } + @Override + public void onError(org.openvpp.jvpp.VppCallbackException reply) { + final java.util.concurrent.CompletableFuture<$base_package.$dto_package.JVppReply> completableFuture; + + synchronized(requests) { + completableFuture = (java.util.concurrent.CompletableFuture<$base_package.$dto_package.JVppReply>) requests.get(reply.getCtxId()); + } + + if(completableFuture != null) { + completableFuture.completeExceptionally(reply); + + synchronized(requests) { + requests.remove(reply.getCtxId()); + } + } + } + $methods } """) @@ -50,12 +67,7 @@ jvpp_facade_callback_method_template = Template(""" } if(completableFuture != null) { - if(reply.retval < 0) { - completableFuture.completeExceptionally(new Exception("Invocation of " + $base_package.$dto_package.$callback_dto.class - + " failed with value " + reply.retval)); - } else { - completableFuture.complete(reply); - } + completableFuture.complete(reply); synchronized(requests) { requests.remove(reply.context); @@ -84,12 +96,7 @@ jvpp_facade_control_ping_method_template = Template(""" requests.remove((($base_package.$future_package.FutureJVppFacade.CompletableDumpFuture) completableFuture).getContextId()); } } else { - if(reply.retval < 0) { - completableFuture.completeExceptionally(new Exception("Invocation of " + $base_package.$dto_package.$callback_dto.class - + " failed with value " + reply.retval)); - } else { - completableFuture.complete(reply); - } + completableFuture.complete(reply); } synchronized(requests) { diff --git a/vpp-api/java/jvpp/gen/jvpp_impl_gen.py b/vpp-api/java/jvpp/gen/jvpp_impl_gen.py index 4e408c364b1..dfec6a743de 100644 --- a/vpp-api/java/jvpp/gen/jvpp_impl_gen.py +++ b/vpp-api/java/jvpp/gen/jvpp_impl_gen.py @@ -39,8 +39,10 @@ public interface JVpp extends java.lang.AutoCloseable { /** * Generic dispatch method for sending requests to VPP + * + * @throws org.openvpp.jvpp.VppInvocationException if send request had failed */ - int send($base_package.$dto_package.JVppRequest request); + int send($base_package.$dto_package.JVppRequest request) throws org.openvpp.jvpp.VppInvocationException; @Override void close(); @@ -76,7 +78,7 @@ public final class JVppImpl implements $base_package.JVpp { } @Override - public int send($base_package.$dto_package.JVppRequest request) { + public int send($base_package.$dto_package.JVppRequest request) throws org.openvpp.jvpp.VppInvocationException { return request.send(this); } @@ -84,23 +86,29 @@ $methods } """) -method_template = Template(""" int $name($base_package.$dto_package.$request request);""") +method_template = Template(""" int $name($base_package.$dto_package.$request request) throws org.openvpp.jvpp.VppInvocationException;""") method_native_template = Template( """ private static native int ${name}0($base_package.$dto_package.$request request);""") -method_impl_template = Template(""" public final int $name($base_package.$dto_package.$request request) { - if(request == null) { - throw new java.lang.NullPointerException("Null request object"); - } +method_impl_template = Template(""" public final int $name($base_package.$dto_package.$request request) throws org.openvpp.jvpp.VppInvocationException { + java.util.Objects.requireNonNull(request,"Null request object"); connection.checkActive(); - return ${name}0(request); + int result=${name}0(request); + if(result<0){ + throw new org.openvpp.jvpp.VppInvocationException("${name}",result); + } + return result; } """) -no_arg_method_template = Template(""" int $name();""") -no_arg_method_native_template = Template(""" private static native int ${name}0();""") -no_arg_method_impl_template = Template(""" public final int $name() { +no_arg_method_template = Template(""" int $name() throws org.openvpp.jvpp.VppInvocationException;""") +no_arg_method_native_template = Template(""" private static native int ${name}0() throws org.openvpp.jvpp.VppInvocationException;""") +no_arg_method_impl_template = Template(""" public final int $name() throws org.openvpp.jvpp.VppInvocationException { connection.checkActive(); - return ${name}0(); + int result=${name}0(); + if(result<0){ + throw new org.openvpp.jvpp.VppInvocationException("${name}",result); + } + return result; } """) diff --git a/vpp-api/java/jvpp/gen/util.py b/vpp-api/java/jvpp/gen/util.py index f951bf828d1..072c9d592f2 100644 --- a/vpp-api/java/jvpp/gen/util.py +++ b/vpp-api/java/jvpp/gen/util.py @@ -45,6 +45,9 @@ def is_reply(name): def is_details(name): return name.lower().endswith(reply_suffixes[1]) or name.lower().endswith(reply_suffixes[2]) +def is_retval_field(name): + return name == 'retval' + dump_suffix = "dump" diff --git a/vpp-api/java/jvpp/jvpp.c b/vpp-api/java/jvpp/jvpp.c index 56c43c9b272..00c50f95beb 100644 --- a/vpp-api/java/jvpp/jvpp.c +++ b/vpp-api/java/jvpp/jvpp.c @@ -39,7 +39,9 @@ #include #undef vl_printfun +#ifndef VPPJNI_DEBUG #define VPPJNI_DEBUG 0 +#endif #if VPPJNI_DEBUG == 1 #define DEBUG_LOG(...) clib_warning(__VA_ARGS__) @@ -160,6 +162,44 @@ JNIEXPORT void JNICALL Java_org_openvpp_jvpp_VppJNIConnection_clientDisconnect vl_client_disconnect_from_vlib(); } +/** +* Send error reply to the requestor +* const char* call pointer to the request name +* int context call context identifier +* int retval result of the operation +*/ +void CallOnError(const char* call, int context, int retval) +{ + DEBUG_LOG("\nCallOnError : callback=%s,retval=%d,context=%d\n",call,clib_net_to_host_u32(retval), clib_net_to_host_u32(context)); + vppjni_main_t * jm = &vppjni_main; + JNIEnv *env = jm->jenv; + if (!env) printf( "CallOnError : env is null!\n"); + if (!jm->callbackClass) { + DEBUG_LOG( "CallOnError : jm->callbackClass is null!\n"); + return; + } + + jmethodID excConstructor = (*env)->GetMethodID(env, callbackExceptionClass, "", "(Ljava/lang/String;II)V"); + if (!excConstructor) { + DEBUG_LOG( "CallOnError : excConstructor is null!\n"); + return; + } + jmethodID callbackExcMethod = (*env)->GetMethodID(env, jm->callbackClass, "onError", "(Lorg/openvpp/jvpp/VppCallbackException;)V"); + if (!callbackExcMethod) { + DEBUG_LOG( "CallOnError : callbackExcMethod is null!\n"); + return; + } + + jobject excObject = (*env)->NewObject(env, callbackExceptionClass, excConstructor,(*env)->NewStringUTF(env, call), clib_net_to_host_u32(context), clib_net_to_host_u32(retval)); + if (!excObject) { + DEBUG_LOG( "CallOnError : excObject is null!\n"); + return; + } + + (*env)->CallVoidMethod(env, jm->callback, callbackExcMethod, excObject); + DEBUG_LOG( "CallOnError : Response sent\n"); +} + // control ping needs to be very first thing called // to attach rx thread to java thread static void vl_api_control_ping_reply_t_handler @@ -192,24 +232,25 @@ static void vl_api_control_ping_reply_t_handler if (was_thread_connected == 0) { JNIEnv *env = jm->jenv; - jmethodID constructor = (*env)->GetMethodID(env, controlPingReplyClass, "", "()V"); - jmethodID callbackMethod = (*env)->GetMethodID(env, jm->callbackClass, "onControlPingReply", "(Lorg/openvpp/jvpp/dto/ControlPingReply;)V"); + if (mp->retval<0){ + CallOnError("controlPing", mp->context, mp->retval); + } else { + jmethodID constructor = (*env)->GetMethodID(env, controlPingReplyClass, "", "()V"); + jmethodID callbackMethod = (*env)->GetMethodID(env, jm->callbackClass, "onControlPingReply", "(Lorg/openvpp/jvpp/dto/ControlPingReply;)V"); - jobject dto = (*env)->NewObject(env, controlPingReplyClass, constructor); + jobject dto = (*env)->NewObject(env, controlPingReplyClass, constructor); - jfieldID contextFieldId = (*env)->GetFieldID(env, controlPingReplyClass, "context", "I"); - (*env)->SetIntField(env, dto, contextFieldId, clib_net_to_host_u32(mp->context)); + jfieldID contextFieldId = (*env)->GetFieldID(env, controlPingReplyClass, "context", "I"); + (*env)->SetIntField(env, dto, contextFieldId, clib_net_to_host_u32(mp->context)); - jfieldID retvalFieldId = (*env)->GetFieldID(env, controlPingReplyClass, "retval", "I"); - (*env)->SetIntField(env, dto, retvalFieldId, clib_net_to_host_u32(mp->retval)); + jfieldID clientIndexFieldId = (*env)->GetFieldID(env, controlPingReplyClass, "clientIndex", "I"); + (*env)->SetIntField(env, dto, clientIndexFieldId, clib_net_to_host_u32(mp->client_index)); - jfieldID clientIndexFieldId = (*env)->GetFieldID(env, controlPingReplyClass, "clientIndex", "I"); - (*env)->SetIntField(env, dto, clientIndexFieldId, clib_net_to_host_u32(mp->client_index)); + jfieldID vpePidFieldId = (*env)->GetFieldID(env, controlPingReplyClass, "vpePid", "I"); + (*env)->SetIntField(env, dto, vpePidFieldId, clib_net_to_host_u32(mp->vpe_pid)); - jfieldID vpePidFieldId = (*env)->GetFieldID(env, controlPingReplyClass, "vpePid", "I"); - (*env)->SetIntField(env, dto, vpePidFieldId, clib_net_to_host_u32(mp->vpe_pid)); - - (*env)->CallVoidMethod(env, jm->callback, callbackMethod, dto); + (*env)->CallVoidMethod(env, jm->callback, callbackMethod, dto); + } } out: diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/VppBaseCallException.java b/vpp-api/java/jvpp/org/openvpp/jvpp/VppBaseCallException.java new file mode 100644 index 00000000000..792af2c69ec --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/VppBaseCallException.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openvpp.jvpp; + +/** + * Base exception representing failed operation of JVpp request call + */ +public abstract class VppBaseCallException extends Exception { + private final String methodName; + private final int errorCode; + + /** + * Constructs an VppCallbackException with the specified api method name and error code. + * + * @param methodName name of a method, which invocation or execution failed + * @param errorCode negative error code value associated with this failure + * @throws NullPointerException if apiMethodName is null + */ + public VppBaseCallException(final String methodName, final int errorCode) { + super(String.format("vppApi.%s failed with error code: %d", methodName, errorCode)); + this.methodName = java.util.Objects.requireNonNull(methodName, "apiMethodName is null!"); + this.errorCode = errorCode; + if(errorCode >= 0) { + throw new IllegalArgumentException("Error code must be < 0. Was " + errorCode + + " for " + methodName ); + } + } + + /** + * Returns name of a method, which invocation failed. + * + * @return method name + */ + public String getMethodName() { + return methodName; + } + + /** + * Returns the error code associated with this failure. + * + * @return a negative integer error code + */ + public int getErrorCode() { + return errorCode; + } +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/VppCallbackException.java b/vpp-api/java/jvpp/org/openvpp/jvpp/VppCallbackException.java new file mode 100644 index 00000000000..3d2a1cb2013 --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/VppCallbackException.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openvpp.jvpp; + +/** + * Callback Exception representing failed operation of JVpp request call + */ +public class VppCallbackException extends VppBaseCallException { + private final int ctxId; + + /** + * Constructs an VppCallbackException with the specified api method name and error code. + * + * @param methodName name of a method, which invocation failed. + * @param ctxId api request context identifier + * @param errorCode negative error code value associated with this failure + * @throws NullPointerException if apiMethodName is null + */ + public VppCallbackException(final String methodName, final int ctxId, final int errorCode ){ + super(methodName, errorCode); + this.ctxId = ctxId; + } + + /** + * Returns api request context identifier. + * + * @return value of context identifier + */ + public int getCtxId() { + return ctxId; + } + +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/VppInvocationException.java b/vpp-api/java/jvpp/org/openvpp/jvpp/VppInvocationException.java new file mode 100644 index 00000000000..298bcd0ae55 --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/VppInvocationException.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openvpp.jvpp; + +/** + * Exception thrown when Vpp jAPI method invocation failed. + */ +public class VppInvocationException extends VppBaseCallException { + /** + * Constructs an VppApiInvocationFailedException with the specified api method name and error code. + * + * @param methodName name of a method, which invocation failed. + * @param errorCode negative error code value associated with this failure + * @throws NullPointerException if apiMethodName is null + */ + public VppInvocationException(final String methodName, final int errorCode) { + super(methodName, errorCode); + } +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/callback/JVppCallback.java b/vpp-api/java/jvpp/org/openvpp/jvpp/callback/JVppCallback.java index c17f2e0aa96..f681e379bfd 100644 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/callback/JVppCallback.java +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/callback/JVppCallback.java @@ -15,9 +15,15 @@ */ package org.openvpp.jvpp.callback; +import org.openvpp.jvpp.VppCallbackException; /** -* Base JVppCallback interface -*/ + * Base JVppCallback interface + */ public interface JVppCallback { + /** + * onError callback handler used to report failing operation + * @param ex VppCallbackException object containing details about failing operation + */ + void onError(VppCallbackException ex); } diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppRequest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppRequest.java index 8cd1534aa13..273e444f601 100644 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppRequest.java +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/dto/JVppRequest.java @@ -17,6 +17,7 @@ package org.openvpp.jvpp.dto; import org.openvpp.jvpp.JVpp; +import org.openvpp.jvpp.VppInvocationException; /** * Base interface for all request DTOs @@ -28,6 +29,6 @@ public interface JVppRequest { * * @return context id of this request. Can be used to track incomming response */ - int send(JVpp jvpp); + int send(JVpp jvpp) throws VppInvocationException; } diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvoker.java b/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvoker.java index 8dab7f5e42d..9219e353cdb 100644 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvoker.java +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvoker.java @@ -17,10 +17,11 @@ package org.openvpp.jvpp.future; -import java.util.concurrent.CompletionStage; import org.openvpp.jvpp.dto.JVppReply; import org.openvpp.jvpp.dto.JVppRequest; +import java.util.concurrent.CompletionStage; + /** * Future facade on top of JVpp */ @@ -30,6 +31,7 @@ public interface FutureJVppInvoker extends AutoCloseable { * Invoke asynchronous operation on VPP * * @return CompletionStage with future result of an async VPP call + * @throws org.openvpp.jvpp.VppInvocationException when send request failed with details */ > CompletionStage send(REQ req); diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvokerFacade.java b/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvokerFacade.java index b005b137b1f..69967a1dbc1 100644 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvokerFacade.java +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/future/FutureJVppInvokerFacade.java @@ -17,16 +17,14 @@ package org.openvpp.jvpp.future; +import org.openvpp.jvpp.JVpp; +import org.openvpp.jvpp.VppInvocationException; +import org.openvpp.jvpp.dto.*; + import java.util.Map; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; -import org.openvpp.jvpp.JVpp; -import org.openvpp.jvpp.dto.ControlPing; -import org.openvpp.jvpp.dto.JVppDump; -import org.openvpp.jvpp.dto.JVppReply; -import org.openvpp.jvpp.dto.JVppReplyDump; -import org.openvpp.jvpp.dto.JVppRequest; /** * Future facade on top of JVpp @@ -59,20 +57,26 @@ public class FutureJVppInvokerFacade implements FutureJVppInvoker { @SuppressWarnings("unchecked") public > CompletionStage send(REQ req) { synchronized(requests) { - final int contextId = jvpp.send(req); - - final CompletableFuture replyCompletableFuture; - if(req instanceof JVppDump) { - replyCompletableFuture = (CompletableFuture) new CompletableDumpFuture<>(contextId); - } else { - replyCompletableFuture = new CompletableFuture<>(); - } - - requests.put(contextId, replyCompletableFuture); - if(req instanceof JVppDump) { - requests.put(jvpp.send(new ControlPing()), replyCompletableFuture); + try { + final CompletableFuture replyCompletableFuture; + final int contextId = jvpp.send(req); + + if(req instanceof JVppDump) { + replyCompletableFuture = (CompletableFuture) new CompletableDumpFuture<>(contextId); + } else { + replyCompletableFuture = new CompletableFuture<>(); + } + + requests.put(contextId, replyCompletableFuture); + if(req instanceof JVppDump) { + requests.put(jvpp.send(new ControlPing()), replyCompletableFuture); + } + return replyCompletableFuture; + } catch (VppInvocationException ex) { + final CompletableFuture replyCompletableFuture = new CompletableFuture<>(); + replyCompletableFuture.completeExceptionally(ex); + return replyCompletableFuture; } - return replyCompletableFuture; } } diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackApiTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackApiTest.java index c3bb272368c..8c976db2397 100644 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackApiTest.java +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackApiTest.java @@ -18,16 +18,12 @@ package org.openvpp.jvpp.test; import org.openvpp.jvpp.JVpp; import org.openvpp.jvpp.JVppImpl; +import org.openvpp.jvpp.VppCallbackException; import org.openvpp.jvpp.VppJNIConnection; import org.openvpp.jvpp.callback.GetNodeIndexCallback; import org.openvpp.jvpp.callback.ShowVersionCallback; import org.openvpp.jvpp.callback.SwInterfaceCallback; -import org.openvpp.jvpp.dto.GetNodeIndex; -import org.openvpp.jvpp.dto.GetNodeIndexReply; -import org.openvpp.jvpp.dto.ShowVersion; -import org.openvpp.jvpp.dto.ShowVersionReply; -import org.openvpp.jvpp.dto.SwInterfaceDetails; -import org.openvpp.jvpp.dto.SwInterfaceDump; +import org.openvpp.jvpp.dto.*; public class CallbackApiTest { @@ -35,14 +31,14 @@ public class CallbackApiTest { @Override public void onGetNodeIndexReply(final GetNodeIndexReply msg) { - System.out.printf("Received GetNodeIndexReply: context=%d, retval=%d, nodeIndex=%d\n", - msg.context, msg.retval, msg.nodeIndex); + System.out.printf("Received GetNodeIndexReply: context=%d, nodeIndex=%d\n", + msg.context, msg.nodeIndex); } @Override - public void onShowVersionReply(final ShowVersionReply msg) { - System.out.printf("Received ShowVersionReply: context=%d, retval=%d, program=%s, version=%s, " + + public void onShowVersionReply(final ShowVersionReply msg) { + System.out.printf("Received ShowVersionReply: context=%d, program=%s, version=%s, " + "buildDate=%s, buildDirectory=%s\n", - msg.context, msg.retval, new String(msg.program), new String(msg.version), + msg.context, new String(msg.program), new String(msg.version), new String(msg.buildDate), new String(msg.buildDirectory)); } @@ -53,12 +49,17 @@ public class CallbackApiTest { new String(msg.interfaceName), msg.l2AddressLength, msg.adminUpDown, msg.linkUpDown, msg.linkSpeed, (int)msg.linkMtu); } + + @Override + public void onError(VppCallbackException ex) { + System.out.printf("Received onError exception: call=%s, context=%d, retval=%d\n", ex.getMethodName(), ex.getCtxId(), ex.getErrorCode()); + } } private static void testCallbackApi() throws Exception { System.out.println("Testing Java callback API"); - JVpp jvpp = new JVppImpl( new VppJNIConnection("CallbackApiTest")); - jvpp.connect( new TestCallback()); + JVpp jvpp = new JVppImpl(new VppJNIConnection("CallbackApiTest")); + jvpp.connect(new TestCallback()); System.out.println("Successfully connected to VPP"); System.out.println("Sending ShowVersion request..."); diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeTest.java index b5e505741d5..bb06c761108 100644 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeTest.java +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CallbackJVppFacadeTest.java @@ -18,9 +18,14 @@ package org.openvpp.jvpp.test; import org.openvpp.jvpp.JVpp; import org.openvpp.jvpp.JVppImpl; +import org.openvpp.jvpp.VppCallbackException; import org.openvpp.jvpp.VppJNIConnection; +import org.openvpp.jvpp.callback.GetNodeIndexCallback; import org.openvpp.jvpp.callback.ShowVersionCallback; import org.openvpp.jvpp.callfacade.CallbackJVppFacade; +import org.openvpp.jvpp.dto.GetNodeIndex; +import org.openvpp.jvpp.dto.GetNodeIndexReply; +import org.openvpp.jvpp.dto.ShowVersionReply; /** * CallbackJVppFacade together with CallbackJVppFacadeCallback allow for setting different callback for each request. @@ -28,15 +33,51 @@ import org.openvpp.jvpp.callfacade.CallbackJVppFacade; */ public class CallbackJVppFacadeTest { - private static ShowVersionCallback showVersionCallback1 = msg -> - System.out.printf("ShowVersionCallback1 received ShowVersionReply: context=%d, retval=%d, program=%s," + - "version=%s, buildDate=%s, buildDirectory=%s\n", msg.context, msg.retval, new String(msg.program), - new String(msg.version), new String(msg.buildDate), new String(msg.buildDirectory)); + private static ShowVersionCallback showVersionCallback1; + private static ShowVersionCallback showVersionCallback2; + private static GetNodeIndexCallback getNodeIndexCallback; - private static ShowVersionCallback showVersionCallback2 = msg -> - System.out.printf("ShowVersionCallback2 received ShowVersionReply: context=%d, retval=%d, program=%s," + - "version=%s, buildDate=%s, buildDirectory=%s\n", msg.context, msg.retval, new String(msg.program), - new String(msg.version), new String(msg.buildDate), new String(msg.buildDirectory)); + static { + getNodeIndexCallback = new GetNodeIndexCallback() { + @Override + public void onGetNodeIndexReply(final GetNodeIndexReply msg) { + System.out.printf("Received GetNodeIndexReply: context=%d, nodeIndex=%d\n", + msg.context, msg.nodeIndex); + } + + @Override + public void onError(VppCallbackException ex) { + System.out.printf("Received onError exception in getNodeIndexCallback: call=%s, reply=%d, context=%d\n", ex.getMethodName(), ex.getErrorCode(), ex.getCtxId()); + } + }; + showVersionCallback2 = new ShowVersionCallback() { + @Override + public void onShowVersionReply(final ShowVersionReply msg) { + System.out.printf("ShowVersionCallback1 received ShowVersionReply: context=%d, program=%s," + + "version=%s, buildDate=%s, buildDirectory=%s\n", msg.context, new String(msg.program), + new String(msg.version), new String(msg.buildDate), new String(msg.buildDirectory)); + } + + @Override + public void onError(VppCallbackException ex) { + System.out.printf("Received onError exception in showVersionCallback2: call=%s, reply=%d, context=%d\n", ex.getMethodName(), ex.getErrorCode(), ex.getCtxId()); + } + + }; + showVersionCallback1 = new ShowVersionCallback() { + @Override + public void onShowVersionReply(final ShowVersionReply msg) { + System.out.printf("ShowVersionCallback1 received ShowVersionReply: context=%d, program=%s," + + "version=%s, buildDate=%s, buildDirectory=%s\n", msg.context, new String(msg.program), + new String(msg.version), new String(msg.buildDate), new String(msg.buildDirectory)); + } + + @Override + public void onError(VppCallbackException ex) { + System.out.printf("Received onError exception in showVersionCallback1: call=%s, reply=%d, context=%d\n", ex.getMethodName(), ex.getErrorCode(), ex.getCtxId()); + } + }; + } private static void testCallbackFacade() throws Exception { System.out.println("Testing CallbackJVppFacade"); @@ -49,6 +90,9 @@ public class CallbackJVppFacadeTest { jvppCallbackFacade.showVersion(showVersionCallback1); jvppCallbackFacade.showVersion(showVersionCallback2); + GetNodeIndex getNodeIndexRequest = new GetNodeIndex(); + getNodeIndexRequest.nodeName = "dummyNode".getBytes(); + jvppCallbackFacade.getNodeIndex(getNodeIndexRequest, getNodeIndexCallback); Thread.sleep(2000); diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/ControlPingTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/ControlPingTest.java index bec302b8089..514bb3ef887 100644 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/ControlPingTest.java +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/ControlPingTest.java @@ -18,6 +18,7 @@ package org.openvpp.jvpp.test; import org.openvpp.jvpp.JVpp; import org.openvpp.jvpp.JVppImpl; +import org.openvpp.jvpp.VppCallbackException; import org.openvpp.jvpp.VppJNIConnection; import org.openvpp.jvpp.callback.ControlPingCallback; import org.openvpp.jvpp.dto.ControlPing; @@ -32,9 +33,15 @@ public class ControlPingTest { jvpp.connect( new ControlPingCallback() { @Override public void onControlPingReply(final ControlPingReply reply) { - System.out.printf("Received ControlPingReply: context=%d, retval=%d, clientIndex=%d vpePid=%d\n", - reply.context, reply.retval, reply.clientIndex, reply.vpePid); + System.out.printf("Received ControlPingReply: context=%d, clientIndex=%d vpePid=%d\n", + reply.context, reply.clientIndex, reply.vpePid); } + + @Override + public void onError(VppCallbackException ex) { + System.out.printf("Received onError exception: call=%s, reply=%d, context=%d ", ex.getMethodName(), ex.getErrorCode(), ex.getCtxId()); + } + }); System.out.println("Successfully connected to VPP"); Thread.sleep(1000); diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CreateSubInterfaceTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CreateSubInterfaceTest.java index f61867e15f1..b3dc1f49491 100644 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/CreateSubInterfaceTest.java +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/CreateSubInterfaceTest.java @@ -16,8 +16,6 @@ package org.openvpp.jvpp.test; -import static java.util.Objects.requireNonNull; - import org.openvpp.jvpp.JVppImpl; import org.openvpp.jvpp.VppJNIConnection; import org.openvpp.jvpp.dto.CreateSubif; @@ -26,6 +24,8 @@ import org.openvpp.jvpp.dto.SwInterfaceDetailsReplyDump; import org.openvpp.jvpp.dto.SwInterfaceDump; import org.openvpp.jvpp.future.FutureJVppFacade; +import static java.util.Objects.requireNonNull; + /** *

Tests sub-interface creation.
Equivalent to:
* @@ -76,9 +76,8 @@ public class CreateSubInterfaceTest { } private static void print(CreateSubifReply reply) { - System.out.printf("CreateSubifReply: context=%d, retval=%d, swIfIndex=%d\n", + System.out.printf("CreateSubifReply: context=%d, swIfIndex=%d\n", reply.context, - reply.retval, reply.swIfIndex); } diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/FutureApiTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/FutureApiTest.java index 745482d1667..0000bcd907c 100644 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/FutureApiTest.java +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/FutureApiTest.java @@ -16,18 +16,14 @@ package org.openvpp.jvpp.test; -import java.util.Objects; -import java.util.concurrent.Future; import org.openvpp.jvpp.VppJNIConnection; -import org.openvpp.jvpp.dto.GetNodeIndex; -import org.openvpp.jvpp.dto.GetNodeIndexReply; -import org.openvpp.jvpp.dto.ShowVersion; -import org.openvpp.jvpp.dto.ShowVersionReply; -import org.openvpp.jvpp.dto.SwInterfaceDetails; -import org.openvpp.jvpp.dto.SwInterfaceDetailsReplyDump; -import org.openvpp.jvpp.dto.SwInterfaceDump; +import org.openvpp.jvpp.dto.*; import org.openvpp.jvpp.future.FutureJVppFacade; +import java.util.Objects; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + public class FutureApiTest { private static void testShowVersion(final FutureJVppFacade jvpp) { @@ -38,12 +34,12 @@ public class FutureApiTest { Objects.requireNonNull(replyFuture,"replyFuture is null"); final ShowVersionReply reply = replyFuture.get(); Objects.requireNonNull(reply,"reply is null"); - System.out.printf("Received ShowVersionReply: context=%d, retval=%d, program=%s, " + + System.out.printf("Received ShowVersionReply: context=%d, program=%s, " + "version=%s, buildDate=%s, buildDirectory=%s\n", - reply.context, reply.retval, new String(reply.program), new String(reply.version), + reply.context, new String(reply.program), new String(reply.version), new String(reply.buildDate), new String(reply.buildDirectory)); } catch (Exception e) { - System.err.printf("ShowVersion request failed:\n"); + System.err.printf("ShowVersion request failed:"+e.getCause()); e.printStackTrace(); } } @@ -62,10 +58,12 @@ public class FutureApiTest { Objects.requireNonNull(replyFuture,"replyFuture is null"); final GetNodeIndexReply reply = replyFuture.get(); Objects.requireNonNull(reply,"reply is null"); - System.out.printf("Received GetNodeIndexReply: context=%d, retval=%d, nodeIndex=%d\n", - reply.context, reply.retval, reply.nodeIndex); + System.out.printf("Received GetNodeIndexReply: context=%d, nodeIndex=%d\n", + reply.context, reply.nodeIndex); + } catch (ExecutionException e) { + System.err.printf("GetNodeIndex request failed:"+e.getCause()); } catch (Exception e) { - System.err.printf("GetNodeIndex request failed:\n"); + System.err.printf("GetNodeIndex request failed:"+e.getCause()); e.printStackTrace(); } } @@ -91,7 +89,7 @@ public class FutureApiTest { } catch(NullPointerException e) { throw new IllegalStateException(e.getMessage()); } catch (Exception e) { - System.err.printf("SwInterfaceDump request failed:\n"); + System.err.printf("SwInterfaceDump request failed:"+e.getCause()); e.printStackTrace(); } } @@ -103,7 +101,6 @@ public class FutureApiTest { new org.openvpp.jvpp.JVppImpl(new VppJNIConnection("FutureApiTest")); final FutureJVppFacade jvppFacade = new FutureJVppFacade(impl); System.out.println("Successfully connected to VPP"); - testShowVersion(jvppFacade); testGetNodeIndex(jvppFacade); testSwInterfaceDump(jvppFacade); diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/L2AclTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/L2AclTest.java index e92b4f5d7b3..d8d04eddfad 100644 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/L2AclTest.java +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/L2AclTest.java @@ -83,25 +83,22 @@ public class L2AclTest { } private static void print(ClassifyAddDelTableReply reply) { - System.out.printf("ClassifyAddDelTableReply: context=%d, retval=%d, " + + System.out.printf("ClassifyAddDelTableReply: context=%d, " + "newTableIndex=%d, skipNVectors=%d, matchNVectors=%d\n", reply.context, - reply.retval, reply.newTableIndex, reply.skipNVectors, reply.matchNVectors); } private static void print(ClassifyAddDelSessionReply reply) { - System.out.printf("ClassifyAddDelSessionReply: context=%d, retval=%d\n", - reply.context, - reply.retval); + System.out.printf("ClassifyAddDelSessionReply: context=%d\n", + reply.context); } private static void print(final InputAclSetInterfaceReply reply) { - System.out.printf("InputAclSetInterfaceReply: context=%d, retval=%d\n", - reply.context, - reply.retval); + System.out.printf("InputAclSetInterfaceReply: context=%d\n", + reply.context); } diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/OnErrorCallbackTest.java b/vpp-api/java/jvpp/org/openvpp/jvpp/test/OnErrorCallbackTest.java new file mode 100644 index 00000000000..46d8558338f --- /dev/null +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/OnErrorCallbackTest.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openvpp.jvpp.test; + +import org.openvpp.jvpp.JVpp; +import org.openvpp.jvpp.JVppImpl; +import org.openvpp.jvpp.VppCallbackException; +import org.openvpp.jvpp.VppJNIConnection; +import org.openvpp.jvpp.callback.GetNodeIndexCallback; +import org.openvpp.jvpp.callback.ShowVersionCallback; +import org.openvpp.jvpp.dto.*; + +public class OnErrorCallbackTest { + + private static class TestCallback implements GetNodeIndexCallback, ShowVersionCallback{ + + @Override + public void onGetNodeIndexReply(final GetNodeIndexReply msg) { + System.out.printf("Received GetNodeIndexReply: context=%d, nodeIndex=%d\n", + msg.context, msg.nodeIndex); + } + @Override + public void onShowVersionReply(final ShowVersionReply msg) { + System.out.printf("Received ShowVersionReply: context=%d, program=%s, version=%s, " + + "buildDate=%s, buildDirectory=%s\n", + msg.context, new String(msg.program), new String(msg.version), + new String(msg.buildDate), new String(msg.buildDirectory)); + } + + @Override + public void onError(VppCallbackException ex) { + System.out.printf("Received onError exception: call=%s, context=%d, retval=%d\n", ex.getMethodName(), ex.getCtxId(), ex.getErrorCode()); + } + } + + private static void testCallbackApi() throws Exception { + System.out.println("Testing Java callback API"); + JVpp jvpp = new JVppImpl(new VppJNIConnection("CallbackApiTest")); + jvpp.connect(new TestCallback()); + System.out.println("Successfully connected to VPP"); + + System.out.println("Sending ShowVersion request..."); + jvpp.send(new ShowVersion()); + + System.out.println("Sending GetNodeIndex request..."); + GetNodeIndex getNodeIndexRequest = new GetNodeIndex(); + getNodeIndexRequest.nodeName = "dummyNode".getBytes(); + jvpp.send(getNodeIndexRequest); + + Thread.sleep(5000); + + System.out.println("Disconnecting..."); + jvpp.close(); + Thread.sleep(1000); + } + + public static void main(String[] args) throws Exception { + testCallbackApi(); + } +} diff --git a/vpp-api/java/jvpp/org/openvpp/jvpp/test/Readme.txt b/vpp-api/java/jvpp/org/openvpp/jvpp/test/Readme.txt index d1ce749f0cc..f9c67ddbcb6 100644 --- a/vpp-api/java/jvpp/org/openvpp/jvpp/test/Readme.txt +++ b/vpp-api/java/jvpp/org/openvpp/jvpp/test/Readme.txt @@ -10,4 +10,5 @@ CallbackApiTest - Similar to ControlPingTest, invokes more complex calls (e.g. i FutureApiTest - Execution of more complex calls using Future based JVpp facade CallbackJVppFacadeTest - Execution of more complex calls using Callback based JVpp facade L2AclTest - Tests L2 ACL creation -CreateSubInterfaceTest - Tests sub-interface creation \ No newline at end of file +CreateSubInterfaceTest - Tests sub-interface creation +OnErrorCallbackTest - simple test failing with onError -- 2.16.6